Partage de technologie

? dans les expressions régulières

2024-07-12

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

Dans les expressions régulières ? Il peut représenter une quantité, 0 ou 1 fois, équivalente à {0, 1}, ou il peut être utilisé comme caractère spécial pour représenter d'autres significations.

correspondance non gourmande

? suivi d'autres qualificatifs de quantité indique une correspondance non gourmande, c'est-à-dire correspondant à la chaîne la plus courte possible recherchée.

Regardons un exemple :

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

Sortie après exécution : abcabc

N'est-ce pas le match le plus court ? Pourquoi a-t-il échoué ?

Cela implique en fait les règles du matching non gourmand :Pour une correspondance non gourmande, le chemin le plus court est mis en correspondance avant la règle suivante. S'il n'y a pas de règle suivante, il est traité comme une correspondance gourmande.

C'est-à-dire que si seul "a.*?" apparaît, il sera toujours traité selon une correspondance gourmande.

Voyons l'utilisation correcte :

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

Sortie après exécution :

  1. afcafc
  2. a
  3. fcafc

Comme vous pouvez le voir, le premier groupe de capture capture la chaîne la plus courte « a » et le deuxième groupe de capture capture « fcafc ».

Examinons les deux autres situations :

  • "(a.*)(.*)" Le premier groupe de capture capturera tout, le deuxième groupe de capture ne signalera pas d'erreur, mais ne capturera rien.
  • "(a.*?)(.*?)" Le premier groupe de capture capturera "a", et le deuxième groupe de capture capturera "fcafc". Puisqu'il n'y a pas d'autres règles plus tard, il sera traité selon une correspondance gourmande. .

Correspond mais ne capture pas (? : motif)

Lorsqu'il est utilisé dans un groupe de capture, ? : est placé avant l'expression régulière pour indiquer la correspondance mais pas la capture, c'est-à-dire que ce groupe de valeurs correspondantes ne peut pas être obtenu via la méthode de groupe.

Voyons un exemple

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

Une erreur sera signalée lors de la capture via group(1), c'est-à-dire qu'elle peut être mise en correspondance mais ne peut pas être capturée. Si ?: est supprimé, il peut être capturé normalement via group(1).

Activer le mode ligne unique (?s)

(?s) active le mode ligne unique sur le côté droit, ce qui fait que . correspond à n'importe quel caractère, y compris le caractère de nouvelle ligne n.

Regardons un exemple :

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

Lors de la capture, (?s) ne peut pas être capturé en tant que groupe de capture, donc "((?s).*)" peut capturer le groupe (1) au maximum, et une erreur sera signalée lors de la capture du groupe (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. }

Après avoir supprimé les (?s), essayez de faire correspondre "abcnsdf". Comme il y a un caractère de nouvelle ligne, la correspondance ne peut pas être terminée, donc rien ne sera affiché.