¿Cómo se (?:)
usan los grupos que no capturan, es decir , en expresiones regulares y para qué sirven?
regex
capturing-group
regex-group
never_had_a_name
fuente
fuente
Respuestas:
Déjame intentar explicar esto con un ejemplo.
Considere el siguiente texto:
Ahora, si aplico la expresión regular a continuación sobre ella ...
... obtendría el siguiente resultado:
Pero no me importa el protocolo, solo quiero el host y la ruta de la URL. Entonces, cambio la expresión regular para incluir el grupo que no captura
(?:)
.Ahora, mi resultado se ve así:
¿Ver? El primer grupo no ha sido capturado. El analizador lo usa para hacer coincidir el texto, pero lo ignora más tarde, en el resultado final.
EDITAR:
Según lo solicitado, permítanme tratar de explicar los grupos también.
Bueno, los grupos tienen muchos propósitos. Pueden ayudarlo a extraer información exacta de una coincidencia más grande (que también se puede nombrar), le permiten volver a emparejar un grupo coincidente anterior y pueden usarse para sustituciones. Probemos algunos ejemplos, ¿de acuerdo?
Imagine que tiene algún tipo de XML o HTML (tenga en cuenta que la expresión regular puede no ser la mejor herramienta para el trabajo , pero es bueno como ejemplo). Desea analizar las etiquetas, por lo que podría hacer algo como esto (he agregado espacios para que sea más fácil de entender):
La primera expresión regular tiene un grupo con nombre (TAG), mientras que la segunda usa un grupo común. Ambas expresiones regulares hacen lo mismo: usan el valor del primer grupo (el nombre de la etiqueta) para que coincida con la etiqueta de cierre. La diferencia es que el primero usa el nombre para que coincida con el valor, y el segundo usa el índice de grupo (que comienza en 1).
Probemos algunas sustituciones ahora. Considere el siguiente texto:
Ahora, usemos esta expresión regular tonta sobre ella:
Esta expresión regular combina palabras con al menos 3 caracteres y usa grupos para separar las primeras tres letras. El resultado es este:
Entonces, si aplicamos la cadena de sustitución:
... sobre él, estamos tratando de usar el primer grupo, agregar un guión bajo, usar el tercer grupo, luego el segundo grupo, agregar otro guión bajo y luego el cuarto grupo. La cadena resultante sería como la de abajo.
También puede usar grupos con nombre para las sustituciones, usando
${name}
.Para jugar con expresiones regulares, recomiendo http://regex101.com/ , que ofrece una buena cantidad de detalles sobre cómo funciona la expresión regular; También ofrece algunos motores regex para elegir.
fuente
Puede usar grupos de captura para organizar y analizar una expresión. Un grupo que no captura tiene el primer beneficio, pero no tiene la sobrecarga del segundo. Todavía puede decir que un grupo sin captura es opcional, por ejemplo.
Supongamos que desea hacer coincidir el texto numérico, pero algunos números podrían escribirse como 1º, 2º, 3º, 4º, ... Si desea capturar la parte numérica, pero no el sufijo (opcional), puede usar un grupo que no sea de captura .
Eso coincidirá con los números en la forma 1, 2, 3 ... o en la forma 1ra, 2da, 3ra, ... pero solo capturará la parte numérica.
fuente
?:
se usa cuando desea agrupar una expresión, pero no desea guardarla como una parte coincidente / capturada de la cadena.Un ejemplo sería algo que coincida con una dirección IP:
Tenga en cuenta que no me importa guardar los primeros 3 octetos, pero la
(?:...)
agrupación me permite acortar la expresión regular sin incurrir en la sobrecarga de capturar y almacenar una coincidencia.fuente
Hace que el grupo no se capture, lo que significa que la subcadena coincidente con ese grupo no se incluirá en la lista de capturas. Un ejemplo en rubí para ilustrar la diferencia:
fuente
(?:)
no produce una captura, no demostrar un ejemplo útil de(?:)
.(?:)
es útil cuando desea agrupar una subexpresión (por ejemplo, cuando desea aplicar cuantificadores a una subexpresión no atómica o si desea restringir el alcance de a|
), pero no desea capturar nada.MOTIVACIÓN HISTÓRICA:
La existencia de grupos que no capturan puede explicarse con el uso de paréntesis.
Considere las expresiones
(a|b)c
ya|bc
, debido a la prioridad de concatenación|
, estas expresiones representan dos idiomas diferentes ({ac, bc}
y{a, bc}
respectivamente).Sin embargo, los paréntesis también se usan como un grupo coincidente (como se explica en las otras respuestas ...).
Cuando desea tener paréntesis pero no capturar la subexpresión, usa GRUPOS NO CAPTURANTES. En el ejemplo,
(?:a|b)c
fuente
Déjame probar esto con un ejemplo:
Código de expresiones regulares:
(?:animal)(?:=)(\w+)(,)\1\2
Cadena de búsqueda:
Línea 1 -
animal=cat,dog,cat,tiger,dog
Línea 2 -
animal=cat,cat,dog,dog,tiger
Línea 3 -
animal=dog,dog,cat,cat,tiger
(?:animal)
-> Grupo 1 no capturado(?:=)
-> Grupo 2 no capturado(\w+)
-> Grupo capturado 1(,)
-> Grupo capturado 2\1
-> resultado del grupo 1 capturado, es decir, en la línea 1 es gato, en la línea 2 es gato, en la línea 3 es perro.\2
-> resultado del grupo 2 capturado, es decir, coma (,)Entonces, en este código al dar
\1
y\2
recordamos o repetimos el resultado del grupo capturado 1 y 2 respectivamente más adelante en el código.Según el orden del código
(?:animal)
debe ser el grupo 1 y(?:=)
debe ser el grupo 2 y continúa.pero al dar
?:
que hacemos que el grupo de coincidencia no sea capturado (lo que no cuenta en el grupo coincidente, entonces el número de agrupación comienza desde el primer grupo capturado y no el no capturado), de modo que la repetición del resultado del grupo de coincidencia(?:animal)
no se puede llamar más tarde en el código.Espero que esto explique el uso del grupo no capturador.
fuente
Los grupos que capturan pueden usar más adelante en la expresión regular para que coincidan O usted puede usarlos en la parte de reemplazo de la expresión regular. Crear un grupo sin captura simplemente exime a ese grupo de ser utilizado por cualquiera de estos motivos.
Los grupos sin captura son excelentes si está intentando capturar muchas cosas diferentes y hay algunos grupos que no desea capturar.
Esa es más o menos la razón por la que existen. Mientras aprende sobre grupos, aprenda sobre Grupos Atómicos , ¡ellos hacen mucho! También hay grupos de búsqueda, pero son un poco más complejos y no se usan tanto.
Ejemplo de uso posterior en la expresión regular (referencia inversa):
<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>
[Encuentra una etiqueta xml (sin soporte ns)]([A-Z][A-Z0-9]*)
es un grupo de captura (en este caso es el nombre de la etiqueta)Más adelante en la expresión regular es lo
\1
que significa que solo coincidirá con el mismo texto que estaba en el primer grupo (el([A-Z][A-Z0-9]*)
grupo) (en este caso, coincide con la etiqueta final).fuente
Bueno, soy un desarrollador de JavaScript y trataré de explicar su importancia con respecto a JavaScript.
Considere un escenario en el que desea hacer coincidir
cat is animal
cuando desea hacer coincidir gato y animal y ambos deberían tener un puntois
intermedio entre ellos.fuente
En expresiones regulares complejas, es posible que surja una situación en la que desee utilizar una gran cantidad de grupos, algunos de los cuales están allí para la coincidencia de repeticiones y otros para proporcionar referencias. Por defecto, el texto que coincide con cada grupo se carga en la matriz de referencia. Cuando tenemos muchos grupos y solo necesitamos poder hacer referencia a algunos de ellos desde la matriz de referencia inversa, podemos anular este comportamiento predeterminado para decirle a la expresión regular que ciertos grupos están ahí solo para el manejo de repeticiones y no necesitan ser capturados y almacenados en la matriz de referencia inversa.
fuente
No puedo comentar las respuestas principales para decir esto: me gustaría agregar un punto explícito que solo está implícito en las respuestas principales:
El grupo
(?...)
que no captura no elimina ningún carácter de la coincidencia completa original, solo reorganiza la expresión regular visualmente para el programador.Para acceder a una parte específica de la expresión regular sin caracteres extraños definidos, siempre deberá usar
.group(<index>)
fuente
tl; dr grupos que no capturan, como su nombre indica son las partes de la expresión regular que no desea que se incluyan en la coincidencia y
?:
es una forma de definir que un grupo no captura.Digamos que tienes una dirección de correo electrónico
[email protected]
. La siguiente expresión regular creará dos grupos , la parte de identificación y la parte @ example.com.(\p{Alpha}*[a-z])(@example.com)
. Por simplicidad, estamos extrayendo todo el nombre de dominio, incluido el@
carácter.Ahora digamos que solo necesita la parte de identificación de la dirección. Lo que desea hacer es tomar el primer grupo del resultado de la coincidencia, rodeado por
()
la expresión regular y la forma de hacerlo es usar la sintaxis de grupo no capturador, es decir?:
. Entonces, la expresión regular(\p{Alpha}*[a-z])(?:@example.com)
devolverá solo la parte de identificación del correo electrónico.fuente
Una cosa interesante que encontré es el hecho de que puedes tener un grupo de captura dentro de un grupo que no es de captura. Eche un vistazo a la expresión regular a continuación para encontrar las URL web correspondientes:
Cadena de URL de entrada:
El primer grupo en mi expresión regular
(?:([A-Za-z]+):)
es un grupo sin captura que coincide con el esquema de protocolo y el:
carácter de dos puntos , es decir,http:
pero cuando estaba ejecutando debajo del código, estaba viendo que el primer índice de la matriz devuelta contenía la cadenahttp
cuando estaba pensando esohttp
y dos puntos:
ambos no serán reportados ya que están dentro de un grupo que no captura.Pensé que si el primer grupo
(?:([A-Za-z]+):)
es un grupo que no captura, entonces por qué está devolviendo unahttp
cadena en la matriz de salida.Entonces, si observa que hay un grupo anidado
([A-Za-z]+)
dentro del grupo que no captura. Ese grupo anidado([A-Za-z]+)
es un grupo de captura (que no tiene?:
al principio) en sí mismo dentro de un grupo sin captura(?:([A-Za-z]+):)
. Es por eso que el textohttp
aún se captura, pero el:
carácter de dos puntos que está dentro del grupo sin captura pero fuera del grupo de captura no se informa en la matriz de salida.fuente
Abra sus DevTools de Google Chrome y luego la pestaña Consola: y escriba esto:
Ejecútalo y verás:
El
JavaScript
motor RegExp captura tres grupos, los elementos con índices 1,2,3. Ahora use la marca de no captura para ver el resultado.El resultado es:
Esto es obvio lo que es el grupo no capturador.
fuente
Creo que te daría la respuesta. No use variables de captura sin verificar que la coincidencia se realizó correctamente.
Las variables de captura
$1
, etc., no son válidas a menos que la coincidencia haya tenido éxito, y tampoco se borran.En el ejemplo anterior, para evitar capturar bronto
$1
,(?:)
se utiliza.Si el patrón coincide,
$1
se captura como el siguiente patrón agrupado.Entonces, la salida será la siguiente:
Es útil si no desea que se guarden las coincidencias.
fuente
Es extremadamente simple, podemos entenderlo con un ejemplo de fecha simple, supongamos que si la fecha se menciona como 1 de enero de 2019 o 2 de mayo de 2019 o cualquier otra fecha y simplemente queremos convertirla al formato dd / mm / aaaa , no necesitaríamos el mes nombre que es enero o febrero para el caso, por lo que para capturar la parte numérica, pero no el sufijo (opcional), puede usar un grupo que no sea de captura.
entonces la expresión regular sería,
Es tan simple como eso.
fuente