Berbagi teknologi

? dalam ekspresi reguler

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Dalam ekspresi reguler,? Dapat mewakili kuantitas, 0 atau 1 kali, setara dengan {0, 1}, atau dapat digunakan sebagai karakter khusus untuk mewakili makna lainnya.

pencocokan yang tidak serakah

? diikuti oleh kualifikasi kuantitas lainnya menunjukkan kecocokan yang tidak serakah, yaitu mencocokkan string terpendek yang dicari.

Mari kita lihat sebuah contoh:

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("a.*?");
  4. Matcher matcher = pattern.matcher("abcabc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. }
  8. }

Output setelah eksekusi: abcabc

Bukankah ini pertandingan terpendek? Mengapa gagal?

Ini sebenarnya melibatkan aturan pencocokan yang tidak serakah:Pencocokan non-serakah, jalur terpendek dicocokkan sebelum aturan berikutnya. Jika tidak ada aturan berikutnya, maka diproses sebagai pencocokan serakah.

Artinya, jika hanya "a.*?" yang muncul, maka akan tetap diproses sesuai dengan pencocokan serakah.

Mari kita lihat penggunaan yang benar:

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("(a.*?)(.*)");
  4. Matcher matcher = pattern.matcher("afcafc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group(0));
  7. System.out.println(matcher.group(1));
  8. System.out.println(matcher.group(2));
  9. }
  10. }

Output setelah eksekusi:

  1. afcafc
  2. a
  3. fcafc

Seperti yang Anda lihat, grup penangkap pertama menangkap string terpendek "a", dan grup penangkap kedua menangkap "fcafc".

Mari kita lihat dua situasi lainnya:

  • "(a.*)(.*)" Grup tangkapan pertama akan menangkap semuanya, grup tangkapan kedua tidak akan melaporkan kesalahan, namun tidak menangkap apa pun.
  • "(a.*?)(.*?)" Grup penangkap pertama akan menangkap "a", dan grup penangkap kedua akan menangkap "fcafc". Karena tidak ada aturan lain nanti, maka akan diproses sesuai dengan pencocokan serakah .

Cocokkan tetapi jangan ditangkap (?:pola)

Saat digunakan dalam grup penangkap, ?: ditempatkan sebelum ekspresi reguler untuk menunjukkan kecocokan tetapi tidak menangkap, artinya grup nilai pencocokan ini tidak dapat diperoleh melalui metode grup.

Mari kita lihat sebuah contoh

  1. @Test
  2. public void test0() {
  3. Pattern pattern = Pattern.compile("\d{4}-(?:[a-z]+)");
  4. Matcher matcher = pattern.matcher("3214-opo");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1)); // 报错
  8. }
  9. }

Kesalahan akan dilaporkan saat menangkap melalui grup(1), yaitu dapat dicocokkan, tetapi tidak dapat ditangkap. Jika ?: dihapus, grup(1) dapat digunakan untuk menangkap secara normal.

Aktifkan mode satu baris (?s)

(?s) mengaktifkan mode satu baris di sisi kanan, membuat .cocok dengan karakter apa pun, termasuk karakter baris baru n.

Mari kita lihat sebuah contoh:

  1. private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
  2. /**
  3. * 从输出结果可知,匹配到了换行符 'n'
  4. */
  5. @Test
  6. public void test4() {
  7. Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN);
  8. Matcher matcher = pattern.matcher("abcnsdf");
  9. if (matcher.matches()) {
  10. System.out.println(matcher.group());
  11. System.out.println(matcher.group(1));
  12. System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错
  13. }
  14. }

Saat menangkap, (?s) tidak dapat ditangkap sebagai grup penangkap, jadi "((?s).*)" paling banyak dapat menangkap grup(1), dan kesalahan akan dilaporkan saat menangkap grup(2).

  1. @Test
  2. public void test5() {
  3. Pattern pattern = Pattern.compile("(.*)");
  4. Matcher matcher = pattern.matcher("abcnsdf");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1));
  8. }
  9. }

Setelah menghapus (?s), coba cocokkan dengan "abcnsdf". Karena ada karakter baris baru, pencocokan tidak dapat diselesaikan, jadi tidak ada output.