PHP 8.5.0 Beta 2 available for testing

Referencias inversas

Fuera de una clase de caracteres, una barra invertida seguida de un dígito mayor que 0 (y posiblemente otros dígitos) es una referencia inversa a un subpatrón de captura anterior (es decir, a su izquierda) en el patrón, siempre que haya habido tantos subpatrones de apertura de captura anteriores.

Sin embargo, si el número decimal que sigue a la barra invertida es menor que 10, siempre se toma como una referencia inversa, y causa un error solo si no hay tantos paréntesis de apertura de captura en todo el patrón. En otras palabras, los paréntesis a los que se hace referencia no necesitan estar a la izquierda de la referencia para números menores que 10. Una "referencia inversa hacia adelante" puede tener sentido cuando se involucra una repetición y el subpatrón a la derecha ha participado en una iteración anterior. Consulte la sección secuencias de escape para obtener más detalles sobre el manejo de los dígitos que siguen a una barra invertida.

Una referencia inversa coincide con lo que realmente coincidió con el subpatrón de captura en la cadena de sujeto actual, en lugar de cualquier cosa que coincida con el subpatrón mismo. Por lo tanto, el patrón (sens|respons)e and \1ibility coincide con "sense and sensibility" y "response and responsibility", pero no con "sense and responsibility". Si la coincidencia sensible (con distinción de mayúsculas y minúsculas) está en vigor en el momento de la referencia inversa, entonces el caso de las letras es relevante. Por ejemplo, ((?i)rah)\s+\1 coincide con "rah rah" y "RAH RAH", pero no con "RAH rah", incluso aunque el subpatrón de captura original se coincidió sin distinción de mayúsculas y minúsculas.

Puede haber más de una referencia inversa al mismo subpatrón. Si un subpatrón no se ha utilizado realmente en una coincidencia particular, entonces cualquier referencia inversa a él siempre falla. Por ejemplo, el patrón (a|(bc))\2 siempre falla si comienza a coincidir con "a" en lugar de "bc". Debido a que pueden haber hasta 99 referencias inversas, todos los dígitos que siguen a la barra invertida se toman como parte de un número de referencia inversa potencial. Si el patrón continúa con un carácter de dígito, entonces algún delimitador debe usarse para terminar la referencia inversa. Si la opción PCRE_EXTENDED está establecida, esto puede ser espacio en blanco. De lo contrario, se puede usar un comentario vacío.

Una referencia inversa que ocurre dentro de los paréntesis a los que se refiere falla cuando el subpatrón se usa por primera vez, por lo que, por ejemplo, (a\1) nunca coincide. Sin embargo, tales referencias pueden ser útiles dentro de subpatrones repetidos. Por ejemplo, el patrón (a|b\1)+ coincide con cualquier número de "a" y también "aba", "ababba" etc. En cada iteración del subpatrón, la referencia inversa coincide con la cadena de caracteres correspondiente a la iteración anterior. Para que esto funcione, el patrón debe ser tal que la primera iteración no necesite coincidir con la referencia inversa. Esto se puede hacer usando alternancia, como en el ejemplo anterior, o por un cuantificador con un mínimo de cero.

La secuencia de escape \g puede usarse para referencias absolutas y relativas de subpatrones. Esta secuencia de escape debe ir seguida de un número sin signo o un número negativo, opcionalmente encerrado entre llaves. Las secuencias \1, \g1 y \g{1} son sinónimas entre sí. El uso de este patrón con un número sin signo puede ayudar a eliminar la ambigüedad inherente al usar dígitos después de una barra invertida. La secuencia ayuda a distinguir referencias inversas de caracteres octales y también facilita tener una referencia inversa seguida de un número literal, por ejemplo \g{2}1.

El uso de la secuencia \g con un número negativo significa una referencia relativa. Por ejemplo, (foo)(bar)\g{-1} coincidiría con la secuencia "foobarbar" y (foo)(bar)\g{-2} coincide con "foobarfoo". Esto puede ser útil en patrones largos como una alternativa a llevar la cuenta del número de subpatrones para referirse a un subpatrón específico anterior.

Las referencias inversas a los subpatrones con nombre pueden lograrse mediante (?P=name), \k<name>, \k'name', \k{name}, \g{name}, \g<name> o \g'name'.

add a note

User Contributed Notes 2 notes

up
13
mnvx at yandex dot ru
9 years ago
Something similar opportunity is DEFINE.

Example:
(?(DEFINE)(?<myname>\bvery\b))(?&myname)\p{Pd}(?&myname).

Expression above will match "very-very" from next sentence:
Define is very-very handy sometimes.
^-------^

How it works. (?(DEFINE)(?<myname>\bvery\b)) - this block defines "myname" equal to "\bvery\b". So, this block "(?&myname)\p{Pd}(?&myname)" equvivalent to "\bvery\b\p{Pd}\bvery\b".
up
0
Steve
2 years ago
The escape sequence \g used as a backreference may not always behave as expected.
The following numbered backreferences refer to the text matching the specified capture group, as documented:
\1
\g1
\g{1}
\g-1
\g{-1}

However, the following variants refer to the subpattern code instead of the matched text:
\g<1>
\g'1'
\g<-1>
\g'-1'

With named backreferences, we may also use the \k escape sequence as well as the (?P=...) construct. The following combinations also refer to the text matching the named capture group, as documented:
\g{name}
\k{name}
\k<name>
\k'name'
(?P=name)

However, these refer to the subpattern code instead of the matched text:
g<name>
\g'name'

In the following example, the capture group searches for a single letter 'a' or 'b', and then the backreference looks for the same letter. Thus, the patterns are expected to match 'aa' and 'bb', but not 'ab' nor 'ba'.

<?php
/* Matches to the following patterns are replaced by 'xx' in the subject string 'aa ab ba bb'. */
$patterns = [
# numbered backreferences (absolute)
'/([ab])\1/', // 'xx ab ba xx'
'/([ab])\g1/', // 'xx ab ba xx'
'/([ab])\g{1}/', // 'xx ab ba xx'
'/([ab])\g<1>/', // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
"/([ab])\g'1'/", // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
'/([ab])\k{1}/', // 'aa ab ba bb' # No group with name "1", backreference to unset group always fails.
'/([ab])\k<1>/', // 'aa ab ba bb' # No group with name "1", backreference to unset group always fails.
"/([ab])\k'1'/", // 'aa ab ba bb' # No group with name "1", backreference to unset group always fails.
'/([ab])(?P=1)/', // NULL # Regex error: "subpattern name must start with a non-digit", (?P=) expects name not number.
# numbered backreferences (relative)
'/([ab])\-1/', // 'aa ab ba bb'
'/([ab])\g-1/', // 'xx ab ba xx'
'/([ab])\g{-1}/', // 'xx ab ba xx'
'/([ab])\g<-1>/', // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
"/([ab])\g'-1'/", // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
'/([ab])\k{-1}/', // 'aa ab ba bb' # No group with name "-1", backreference to unset group always fails.
'/([ab])\k<-1>/', // 'aa ab ba bb' # No group with name "-1", backreference to unset group always fails.
"/([ab])\k'-1'/", // 'aa ab ba bb' # No group with name "-1", backreference to unset group always fails.
'/([ab])(?P=-1)/', // NULL # Regex error: "subpattern name expected", (?P=) expects name not number.
# named backreferences
'/(?<name>[ab])\g{name}/', // 'xx ab ba xx'
'/(?<name>[ab])\g<name>/', // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
"/(?<name>[ab])\g'name'/", // 'xx xx xx xx' # unexpected behavior, backreference matches both 'a' and 'b'.
'/(?<name>[ab])\k{name}/', // 'xx ab ba xx'
'/(?<name>[ab])\k<name>/', // 'xx ab ba xx'
"/(?<name>[ab])\k'name'/", // 'xx ab ba xx'
'/(?<name>[ab])(?P=name)/', // 'xx ab ba xx'
];

foreach (
$patterns as $pat)
echo
" '$pat',\t// " . var_export(@preg_replace($pat, 'xx', 'aa ab ba bb'), 1) . PHP_EOL;
?>
To Top