Condivisione della tecnologia

? nelle espressioni regolari

2024-07-12

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

Nelle espressioni regolari,? Può rappresentare una quantità, 0 o 1 volte, equivalente a {0, 1} oppure può essere utilizzato come carattere speciale per rappresentare altri significati.

abbinamento non avido

? seguito da altri qualificatori di quantità indica una corrispondenza non greedy, ovvero una corrispondenza con la stringa più breve possibile cercata.

Diamo un'occhiata a un esempio:

  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 dopo l'esecuzione: abcbc

Non è la partita più breve? Perché ha fallito?

Ciò in realtà coinvolge le regole dell'abbinamento non avido:Per l'abbinamento non greedy, il percorso più breve viene abbinato prima della regola successiva. Se non esiste una regola successiva, viene elaborato come abbinamento greedy.

Vale a dire, se appare solo "a.*?", verrà comunque elaborato secondo la corrispondenza greedy.

Vediamo l’utilizzo corretto:

  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 dopo l'esecuzione:

  1. afcafc
  2. a
  3. fcafc

Come puoi vedere, il primo gruppo di acquisizione cattura la stringa più breve "a" e il secondo gruppo di acquisizione cattura "fcafc".

Diamo un’occhiata alle altre due situazioni:

  • "(a.*)(.*)" Il primo gruppo di acquisizione catturerà tutto, il secondo gruppo di acquisizione non segnalerà un errore, ma non catturerà nulla.
  • "(a.*?)(.*?)" Il primo gruppo di acquisizione catturerà "a" e il secondo gruppo di acquisizione catturerà "fcafc". Poiché non ci sono altre regole in seguito, verrà elaborato in base alla corrispondenza greedy .

Abbina ma non cattura (?:modello)

Se utilizzato in un gruppo di acquisizione, ?: viene posizionato prima dell'espressione regolare per indicare la corrispondenza ma non l'acquisizione, ovvero questo gruppo di valori corrispondenti non può essere ottenuto tramite il metodo group.

Vediamo un esempio

  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. }

Verrà segnalato un errore durante l'acquisizione tramite group(1), ovvero è possibile far corrispondere ma non acquisire. Se ?: viene rimosso, può essere catturato normalmente tramite group(1).

Abilita la modalità a linea singola (?s)

(?s) attiva la modalità a riga singola sul lato destro, facendo corrispondere . a qualsiasi carattere, incluso il carattere di nuova riga n.

Diamo un'occhiata a un esempio:

  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. }

Durante l'acquisizione, (?s) non può essere catturato come gruppo di acquisizione, quindi "((?s).*)" può catturare al massimo il gruppo(1) e verrà segnalato un errore durante l'acquisizione del gruppo(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. }

Dopo aver rimosso le (?s), prova a trovare la corrispondenza con "abcnsdf". Poiché è presente un carattere di nuova riga, la corrispondenza non può essere completata, quindi non verrà restituito nulla.