Buscar..


Grupos de captura básicos

Un grupo es una sección de una expresión regular entre paréntesis () . Esto se denomina comúnmente "subexpresión" y tiene dos propósitos:

  • Hace que la subexpresión sea atómica, es decir, que coincida, falle o se repita como un todo.
  • La parte del texto que coincidió es accesible en el resto de la expresión y el resto del programa.

Los grupos están numerados en los motores de expresiones regulares, comenzando con 1. Tradicionalmente, el número máximo de grupos es 9, pero muchos de los sabores de expresiones regulares modernas admiten un mayor número de grupos. El grupo 0 siempre coincide con todo el patrón, de la misma manera que rodea toda la expresión regular con corchetes.

El número ordinal aumenta con cada paréntesis de apertura, independientemente de si los grupos se colocan uno tras otro o anidados:

foo(bar(baz)?) (qux)+|(bla)
   1   2       3      4

grupos y sus numeros

Después de que una expresión logre una coincidencia global, todos sus grupos estarán en uso, ya sea que un grupo en particular haya logrado igualar algo o no.

Un grupo puede ser opcional, como (baz)? arriba, o en una parte alternativa de la expresión que no se usó de la coincidencia, como (bla) arriba. En estos casos, los grupos no coincidentes simplemente no contendrán ninguna información.

Si se coloca un cuantificador detrás de un grupo, como en (qux)+ arriba, el recuento global de grupos de la expresión permanece igual. Si un grupo coincide más de una vez, su contenido será la última vez que se produzca la coincidencia. Sin embargo, las versiones modernas de expresiones regulares permiten acceder a todas las apariciones de subincidencia.


Si desea recuperar la fecha y el nivel de error de una entrada de registro como esta:

2012-06-06 12:12.014 ERROR: Failed to connect to remote end

Podrías usar algo como esto:

^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$

Esto extraería la fecha de la entrada de registro 2012-06-06 como grupo de captura 1 y el nivel de error ERROR como grupo de captura 2.

Referencias y grupos no capturadores

Dado que los grupos están "numerados", algunos motores también admiten la coincidencia con lo que un grupo ha vuelto a hacer coincidir previamente.

Suponiendo que quisiera hacer coincidir algo donde dos cuerdas iguales de la longitud tres se dividen por un $ que usaría:

(.{3})\$\1

Esto coincidiría con cualquiera de las siguientes cadenas:

"abc$abc"
"a b$a b"
"af $af "
"   $   "

Si desea que un grupo no esté numerado por el motor, puede declararlo como no capturado. Un grupo que no captura se ve así:

(?:)

Son particularmente útiles para repetir un cierto patrón cualquier cantidad de veces, ya que un grupo también puede usarse como un "átomo". Considerar:

(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2

Esto coincidirá con dos entradas de registro en las líneas adyacentes que tienen la misma marca de tiempo y la misma entrada.

Grupos de captura con nombre

Algunos sabores de expresiones regulares permiten grupos de captura con nombre . En lugar de hacerlo mediante un índice numérico, puede referirse a estos grupos por su nombre en el código posterior, es decir, en las referencias inversas, en el patrón de reemplazo y en las siguientes líneas del programa.

Los índices numéricos cambian a medida que cambia el número o la disposición de los grupos en una expresión, por lo que son más frágiles en comparación.

Por ejemplo, para hacer coincidir una palabra ( \w+ ) entre comillas simples o dobles ( ['"] ), podríamos usar:

(?<quote>['"])\w+\k{quote}

Lo que equivale a:

(['"])\w+\1

En una situación simple como esta, un grupo de captura numerado y regular no tiene ningún inconveniente.

En situaciones más complejas, el uso de grupos con nombre hará que la estructura de la expresión sea más evidente para el lector, lo que mejora la capacidad de mantenimiento.

El análisis de archivos de registro es un ejemplo de una situación más compleja que se beneficia de los nombres de grupo. Este es el formato de registro común de Apache (CLF):

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

La siguiente expresión captura las partes en grupos nombrados:

(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)

La sintaxis depende del sabor, los más comunes son:

  • (?<name>...)
  • (?'name'...)
  • (?P<name>...)

Backreferences:

  • \k<name>
  • \k{name}
  • \k'name'
  • \g{name}
  • (?P=name)

En la versión .NET, puede tener varios grupos compartiendo el mismo nombre, usarán pilas de captura .

En PCRE, debe habilitarlo explícitamente utilizando el modificador (?J) ( PCRE_DUPNAMES ), o utilizando el grupo de restablecimiento de rama (?|) . Sin embargo, solo el último valor capturado será accesible.

(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow