Compartir tecnología

? en expresiones regulares

2024-07-12

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

¿En expresiones regulares? Puede representar cantidad, 0 o 1 veces, equivalente a {0, 1}, o puede usarse como un carácter especial para representar otros significados.

coincidencia no codiciosa

? seguido de otros calificadores de cantidad indica una coincidencia no codiciosa, es decir, que coincide con la cadena más corta posible que se busca.

Veamos un ejemplo:

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

Salida después de la ejecución: abcabc

¿No es el partido más corto? ¿Por qué fracasó?

En realidad, esto involucra las reglas de coincidencia no codiciosa:Para una coincidencia no codiciosa, la ruta más corta coincide antes de la siguiente regla. Si no hay una regla siguiente, se procesa como una coincidencia codiciosa.

Es decir, si solo aparece "a.*?", aún se procesará según la coincidencia codiciosa.

Veamos el uso correcto:

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

Salida después de la ejecución:

  1. afcafc
  2. a
  3. fcafc

Como puede ver, el primer grupo de captura captura la cadena más corta "a" y el segundo grupo de captura captura "fcafc".

Echemos un vistazo a las otras dos situaciones:

  • "(a.*)(.*)" El primer grupo de captura capturará todo, el segundo grupo de captura no informará un error, pero no capturará nada.
  • "(a.*?)(.*?)" El primer grupo de captura capturará "a", y el segundo grupo de captura capturará "fcafc". Como no hay otras reglas más adelante, se procesará de acuerdo con la coincidencia codiciosa. .

Coincidir pero no capturar (?:patrón)

Cuando se usa en un grupo de captura, ?: se coloca antes de la expresión regular para indicar coincidencia pero no captura, es decir, este grupo de valores coincidentes no se puede obtener mediante el método de grupo.

Veamos ejemplos

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

Se informará un error al capturar a través del grupo (1), es decir, se puede coincidir pero no se puede capturar. Si ?: se elimina, se puede capturar normalmente a través del grupo (1).

Habilitar el modo de línea única (?s)

(?s) activa el modo de una sola línea en el lado derecho, lo que hace que . coincida con cualquier carácter, incluido el carácter de nueva línea n.

Veamos un ejemplo:

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

Al capturar, (?s) no se puede capturar como un grupo de captura, por lo que "((?s).*)" puede capturar el grupo (1) como máximo, y se informará un error al capturar el grupo (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. }

Después de eliminar (? s), intente hacer coincidir "abcnsdf". Debido a que hay un carácter de nueva línea, la coincidencia no se puede completar, por lo que no se generará nada.