Regular Expressions
Referencia posterior
Buscar..
Lo esencial
Las referencias anteriores se utilizan para hacer coincidir el mismo texto que un grupo de captura coincidió previamente. Esto ayuda tanto a reutilizar partes anteriores de su patrón como a asegurar que dos partes de una cadena coinciden.
Por ejemplo, si está intentando verificar que una cadena tiene un dígito de cero a nueve, un separador, como guiones, barras o incluso espacios, una letra minúscula, otro separador, luego otro dígito de cero a nueve, podría use un regex como este:
[0-9][-/ ][a-z][-/ ][0-9]
Esto coincidiría con 1-a-4
, pero también coincidiría con 1-a/4
o 1 a-4
. Si queremos que los separadores coincidan, podemos usar un grupo de captura y una referencia posterior. La referencia posterior verá la coincidencia encontrada en el grupo de captura indicado y asegurará que la ubicación de la referencia posterior coincida exactamente.
Usando nuestro mismo ejemplo, la expresión regular se convertiría en:
[0-9]([-/ ])[a-z]\1[0-9]
El \1
denota el primer grupo de captura en el patrón. Con este pequeño cambio, la expresión regular ahora combina 1-a-4
o 1 a 4
pero no 1 a-4
o 1-a/4
.
El número a usar para su referencia de respaldo depende de la ubicación de su grupo de captura. El número puede ser de uno a nueve y se puede encontrar contando sus grupos de captura.
([0-9])([-/ ])[a-z][-/ ]([0-9])
|--1--||--2--| |--3--|
Los grupos de captura anidados cambian este conteo ligeramente. Primero cuenta el grupo de captura exterior, luego el siguiente nivel y continúa hasta que abandonas el nido:
(([0-9])([-/ ]))([a-z])
|--2--||--3--|
|-------1------||--4--|
Referencias ambiguas
Problema: necesita hacer coincidir el texto de un determinado formato, por ejemplo:
1-a-0
6/p/0
4 g 0
Eso es un dígito, un separador (uno de -
, /
, o un espacio), una letra, el mismo separador y un cero.
Solución ingenua: adaptando la expresión regular del ejemplo de Conceptos básicos , puede encontrar esta expresión regular:
[0-9]([-/ ])[a-z]\10
Pero eso probablemente no funcionará. La mayoría de los tipos de expresiones regulares admiten más de nueve grupos de captura, y muy pocos de ellos son lo suficientemente inteligentes como para darse cuenta de que, dado que solo hay un grupo de captura, \10
debe ser una referencia inversa al grupo 1 seguido de un 0
literal. La mayoría de los sabores lo tratarán como una referencia inversa al grupo 10. Algunos de ellos lanzarán una excepción porque no hay un grupo 10; el resto simplemente no coincidirá.
Hay varias formas de evitar este problema. Una es usar grupos con nombre (y referencias con nombre):
[0-9](?<sep>[-/ ])[a-z]\k<sep>0
Si su lenguaje de expresiones regulares lo admite, el formato \g{n}
(donde n
es un número) puede incluir el número de referencia inversa entre paréntesis para separarlo de cualquier dígito después de él:
[0-9]([-/ ])[a-z]\g{1}0
Otra forma es usar el formato de expresiones regulares extendido, separando los elementos con espacios en blanco insignificantes (en Java, tendrá que escapar del espacio entre paréntesis):
(?x) [0-9] ([-/ ]) [a-z] \1 0
Si su versión de expresiones regulares no es compatible con esas características, puede agregar una sintaxis innecesaria pero inofensiva, como un grupo que no captura:
[0-9]([-/ ])[a-z](?:\1)0
... o un cuantificador ficticio (esta es posiblemente la única circunstancia en la que {1}
es útil):
[0-9]([-/ ])[a-z]\1{1}0