شنبه ۲۹ دي ۱۴۰۳
Tut24 آموزش برنامه نویسی و مجله تخصصی فناوری ورود/عضویت

آموزش جاوا - عبارات با قاعده

جاوا بسته‌ی java.util.regex را برای تطبیق الگو با عبارات با قاعده فراهم می‌کند. عبارات با قاعده در جاوا بسیار شبیه به زبان برنامه‌نویسی پرل (Perl) هستند و بسیار آسان برای یادگیری هستند.

عبارت با قاعده یک توالی خاص از کاراکترهاست که به شما در تطبیق یا پیدا کردن رشته‌ها یا مجموعه‌های رشته‌ها به کمک یک نحو ویژه کمک می‌کند. آنها می‌توانند برای جستجو، ویرایش یا تغییر متن و داده‌ها استفاده شوند.

بسته‌ی java.util.regex در اصل از سه کلاس زیر تشکیل شده است:

  • کلاس Pattern - یک شیی Pattern نماینده‌ی کامپایل شده‌ی یک عبارت با قاعده است. کلاس Pattern هیچ سازنده‌ی عمومی ندارد. برای ایجاد یک الگو، باید ابتدا یکی از متد‌های compile() عمومی و استاتیک آن را فراخوانی کنید که سپس یک شیی Pattern را برگرداند. این متدها یک عبارت با قاعده را به عنوان آرگومان اول قبول می‌کنند.

  • کلاس Matcher - یک شیی Matcher موتوری است که الگو را تفسیر می‌کند و عملیات تطبیق را در برابر یک رشته ورودی انجام می‌دهد. مشابه کلاس Pattern، کلاس Matcher سازنده‌ی عمومی ندارد. شما می‌توانید یک شیی Matcher را با فراخوانی متد matcher() روی یک شیی Pattern به دست آورید.

  • PatternSyntaxException - یک شیی PatternSyntaxException یک استثناء بدون بررسی است که خطا در نحو عبارت با قاعده را نشان می‌دهد.

گروه‌های ضبط‌شونده (Capturing Groups)

گروه‌های ضبط‌شونده یک روشی هستند برای تلقی دسته‌ای از کاراکترها به عنوان یک واحد تکی. آنها با قرار دادن کاراکترهایی که می‌خواهید گروه‌بندی شوند درون یک مجموعه پرانتزی ایجاد می‌شوند. به عنوان مثال، عبارت با قاعده (سگ) یک گروه تکی شامل حروف "س"، "گ" و "گ" ایجاد می‌کند.

گروه‌های ضبط‌شونده با شمارش پرانتزهای بازشونده از چپ به راست شماره‌گذاری می‌شوند. به عنوان مثال در عبارت ((A)(B(C))) چهار گروه به شرح زیر وجود دارد:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

برای یافتن تعداد گروه‌های موجود در عبارت، متد groupCount را روی یک شیی Matcher فراخوانی کنید. متد groupCount یک عدد صحیح برمی‌گرداند که تعداد گروه‌های ضبط‌شونده موجود در عبارت را نشان می‌دهد.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches {

   public static void main( String args[] ) {
      // String to be scanned to find the pattern.
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(.*)(\\d+)(.*)";

      // Create a Pattern object
      Pattern r = Pattern.compile(pattern);

      // Now create matcher object.
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
      }else {
         System.out.println("NO MATCH");
      }
   }
}

این عبارت نتیجه‌ی زیر را تولید خواهد کرد −

خروجی

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0

نحوی عبارات با قاعده (Regular Expression Syntax)

در ادامه جدولی قرار دارد که نمادهای خاص عبارات با قاعده موجود در جاوا را بیان می‌کند −

زیرعبارت تطابق
^ شروع خط را تطابق می‌دهد.
$ پایان خط را تطابق می‌دهد.
. هر کاراکتر تکی به جز خط جدید را تطابق می‌دهد. استفاده از گزینه m امکان تطابق با خط جدید را نیز فراهم می‌کند.
[...] هر کاراکتر تکی درون براکت‌ها را تطابق می‌دهد.
[^...] هر کاراکتر تکی به جز کاراکترهای درون براکت‌ها را تطابق می‌دهد.
\A شروع رشته کامل را تطابق می‌دهد.
\z پایان رشته کامل را تطابق می‌دهد.
\Z پایان رشته کامل به جز قابل قبول درپایان خط را تطابق می‌دهد.
re* تطابق با ۰ یا بیشتر بار تکرار عبارت قبلی را می‌دهد.
re+ تطابق با ۱ یا بیشتر از مورد قبلی را می‌دهد.
re? تطابق با ۰ یا ۱ بار تکرار عبارت قبلی را می‌دهد.
re{ n} تطابق با دقیقا n بار تکرار عبارت قبلی را می‌دهد.
re{ n,} تطابق با n یا بیشتر بار تکرار عبارت قبلی را می‌دهد.
re{ n, m} تطابق با حداقل n و حداکثر m بار تکرار عبارت قبلی را می‌دهد.
a| b تطابق با یا a یا b را می‌دهد.
(re) عبارت‌های با قاعده را گروه‌بندی می‌کند و متن تطابق داده‌شده را به یاد می‌آورد.
(?: re) عبارت‌های با قاعده را بدون به یاد آوردن متن تطابق داده‌شده گروه‌بندی می‌کند.
(?> re) الگوی مستقل را بدون بازگشت پشتیبانی تطابق می‌دهد.
\w تطابق با کاراکترهای کلمه‌ای را می‌دهد.
\W تطابق با کاراکترهای غیر کلمه‌ای را می‌دهد.
\s تطابق با فضای خالی. معادل [\t\n\r\f] است.
\S تطابق با غیر فضای خالی را می‌دهد.
\d تطابق با ارقام. معادل [0-9] است.
\D تطابق با عدم ارقام را می‌دهد.
\A تطابق با شروع رشته را می‌دهد.
\Z تطابق با پایان رشته. اگر خط جدید وجود داشته باشد، قبل از خط جدید تطابق می‌دهد.
\z تطابق با پایان رشته را می‌دهد.
\G تطابق با نقطه‌ای که آخرین تطابق تمام شده است.
\n بازارسانی به شماره گروه ضبط شده "n".
\b تطابق با مرزهای کلمه در خارج از براکت. تطابق با backspace (0x08) درون براکت را می‌دهد.
\B تطابق با مرزهای غیر کلمه‌ای را می‌دهد.
\n, \t, و غیره تطابق با خطوط جدید، بازگشت خط، تب و غیره را می‌دهد.
\Q به عبارتی تمام کاراکترها تا \E را متمم می‌کند.
\E اتمام نقل قول‌هایی که با \Q شروع شده‌اند.

روش‌های کلاس Matcher

در ادامه فهرستی از روش‌های نمونه کلاس قابل استفاده قرار داده شده است −

روش‌های اندیس

روش‌های اندیس مقادیر اندیس مفیدی را ارائه می‌دهند که دقیقاً نشان می‌دهند کجا تطابق در رشته ورودی پیدا شده است −

شماره روش و توضیحات
1

public int start()

شاخص شروع تطابق قبلی را برمی‌گرداند.

2

public int start(int group)

شاخص شروع زیررشته‌ای را که توسط گروه مشخص شده در عملیات تطابق قبلی ضبط شده است، برمی‌گرداند.

3

public int end()

آفست پس از آخرین کاراکتر تطابق داده شده را برمی‌گرداند.

4

public int end(int group)

آفست پس از آخرین کاراکتر زیررشته‌ای را که توسط گروه مشخص شده در عملیات تطابق قبلی ضبط شده است، برمی‌گرداند.

روش‌های مطالعه

روش‌های مطالعه رشته ورودی را بررسی می‌کنند و مقدار منطقی بولینی برمی‌گردانند که نشان می‌دهد الگو یافت می‌شود یا خیر −

شماره روش و توضیحات
1

public boolean lookingAt()

تلاش برای تطابق دنباله ورودی را از ابتدای منطقه با الگو انجام می‌دهد.

2

public boolean find()

تلاش برای یافتن زیردنباله بعدی از دنباله ورودی را که با الگو مطابقت دارد انجام می‌دهد.

3

public boolean find(int start)

این مطابق‌ساز را ریست می‌کند و سپس تلاش می‌کند تا زیردنباله بعدی از دنباله ورودی را که با الگو مطابقت دارد را از شاخص مشخص شده آغاز کند.

4

public boolean matches()

تلاش برای تطابق کامل منطقه با الگو را انجام می‌دهد.

روش‌های جایگزینی

روش‌های جایگزینی روش‌های مفیدی برای جایگزینی متن در یک رشته ورودی هستند −

شماره روش و توضیحات
1

public Matcher appendReplacement(StringBuffer sb, String replacement)

یک مرحله نهایی غیرمتمم اضافه و جایگزین را پیاده‌سازی می‌کند.

2

public StringBuffer appendTail(StringBuffer sb)

یک مرحله نهایی غیرمتمم اضافه و جایگزین را پیاده‌سازی می‌کند.

3

public String replaceAll(String replacement)

هر زیردنباله از دنباله ورودی که با الگو مطابقت دارد را با رشته جایگزین داده شده جایگزین می‌کند.

4

public String replaceFirst(String replacement)

نخستین زیردنباله از دنباله ورودی که با الگو مطابقت دارد را با رشته جایگزین داده شده جایگزین می‌کند.

5

public static String quoteReplacement(String s)

یک رشته جایگزین صریح برای رشته مشخص شده را برمی‌گرداند. این روش یک رشته تولید می‌کند که به عنوان یک جایگزین صریح s در روش appendReplacement کلاس Matcher کار خواهد کرد.

روش‌های شروع و پایان

در زیر مثالی آمده است که تعداد ظهور کلمه "cat" در رشته ورودی را محاسبه می‌کند −

مثال

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches {

   private static final String REGEX = "\\bcat\\b";
   private static final String INPUT = "cat cat cat cattie cat";

   public static void main( String args[] ) {
      Pattern p = Pattern.compile(REGEX);
      Matcher m = p.matcher(INPUT);   // get a matcher object
      int count = 0;

      while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}

این عبارت نتیجه زیر را به دنبال دارد −

خروجی

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

می‌توانید ببینید که این مثال از مرزهای کلمه استفاده می‌کند تا اطمینان حاصل شود که حروف "c"، "a" و "t" فقط یک زیررشته درون یک کلمه بلندتر نیستند. همچنین اطلاعات مفیدی درباره محل رخداد تطابق در رشته ورودی ارائه می‌دهد.

متد start شاخص شروع زیررشته متصل شده توسط گروه مشخص شده در عملیات قبلی تطابق را برمی‌گرداند و متد end شاخص آخرین حرف تطابق‌یافته، به علاوه یک برمی‌گرداند.

متد‌های matches و lookingAt

متد‌های matches و lookingAt هر دو تلاش می‌کنند تا یک دنباله ورودی را با یک الگو تطابق دهند. اما تفاوت آنها در این است که matches نیاز دارد تا کل دنباله ورودی تطابق داشته باشد، در حالی که lookingAt این نیاز را ندارد.

هر دو متد همیشه از ابتدای رشته ورودی شروع می‌کنند. در ادامه مثالی ارائه شده است که عملکرد را توضیح می‌دهد −

مثال

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches {

   private static final String REGEX = "foo";
   private static final String INPUT = "fooooooooooooooooo";
   private static Pattern pattern;
   private static Matcher matcher;

   public static void main( String args[] ) {
      pattern = Pattern.compile(REGEX);
      matcher = pattern.matcher(INPUT);

      System.out.println("Current REGEX is: "+REGEX);
      System.out.println("Current INPUT is: "+INPUT);

      System.out.println("lookingAt(): "+matcher.lookingAt());
      System.out.println("matches(): "+matcher.matches());
   }
}

این عمل، نتیجه زیر را تولید می‌کند −

خروجی

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false

متدهای replaceFirst و replaceAll

متدهای replaceFirst و replaceAll متنی که با یک عبارت منظم مطابقت داشته باشد را جایگزین می‌کنند. همانطور که از نامشان پیداست، replaceFirst اولین رخداد را جایگزین می‌کند و replaceAll تمام رخدادها را جایگزین می‌کند.

در اینجا نمونه‌ای برای توضیح عملکرد آنها آورده شده است −

نمونه

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches {

   private static String REGEX = "dog";
   private static String INPUT = "The dog says meow. " + "All dogs say meow.";
   private static String REPLACE = "cat";

   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      
      // get a matcher object
      Matcher m = p.matcher(INPUT); 
      INPUT = m.replaceAll(REPLACE);
      System.out.println(INPUT);
   }
}

این عمل باعث تولید نتیجه زیر می‌شود −

خروجی

The cat says meow. All cats say meow.

متدهای appendReplacement و appendTail

کلاس Matcher همچنین متدهای appendReplacement و appendTail را برای جایگزینی متن فراهم می‌کند.

اینجا مثالی برای توضیح عملکرد آنها آمده است −

مثال

The cat says meow. All cats say meow.

متدهای appendReplacement و appendTail

کلاس Matcher نیز متدهای appendReplacement و appendTail را برای جایگزینی متن فراهم می‌کند.

اینجا مثالی برای توضیح عملکرد آنها آمده است −

مثال

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches {

   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoob";
   private static String REPLACE = "-";
   public static void main(String[] args) {

      Pattern p = Pattern.compile(REGEX);
      
      // get a matcher object
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()) {
         m.appendReplacement(sb, REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

این عمل نتیجه زیر را تولید خواهد کرد :

خروجی

-foo-foo-foo-