Detalles de las Expresiones Regulares
Introducción
La sintaxis y semántica de las expresiones regulares
soportadas por PCRE se describe a continuación. Las
expresiones reglurares son descritas en la documentación
de Perl y en varios libros más, algunos de los cuales
contienen numerosos ejemplos. El libro "Mastering Regular
Expressions" de Jeffrey Friedl, publicado por O'Reilly (ISBN
1-56592-257-3), las cubre con gran detalle. El propósito
de la presente descripción es el de servir como
documentación de referencia.
Una expresión regular es un patrón que es comparado
contra una cadena de asunto, de izquierda a derecha. La
mayorÃa de caracteres se representan a ellos mismos en un
patrón, y coinciden con el caracter correspondiente en el
asunto. Como ejemplo trivial, el patrón The quick
brown fox coincide con una porción de la cadena
de asunto que sea idéntica al patrón dado.
Meta-caracteres
El poder de las expresiones regulares proviene de la habilidad
de incluir alternativas y repeticiones en el
patrón. Éstos recursos son codificados en el
patrón mediante el uso de
meta-caracteres, los cuales no se
representan a ellos mismos, en su lugar, son interpretados de
una forma especial.
Hay dos conjuntos diferentes de meta-caracteres: aquellos que son
reconocidos en cualquier parte dentro del patrón excepto
entre corchetes cuadrados, y aquellos que son reconocidos entre
corchetes cuadrados. Por fuera de tales corchetes, los
meta-caracteres son los siguientes:
- \
caracter de escape general con varios
usos
- ^
aserción de inicio de la cadena de
asunto (o lÃnea, en modo
multilÃnea)
- $
aserción de fin de la cadena de
asunto (o lÃnea, en modo
multilÃnea)
- .
coincide con cualquier caracter excepto la
nueva lÃnea (por defecto)
- [
inicia la definición de clases de
caracteres
- ]
fin de la definición de clases de
caracteres
- |
inicio de rama
alternativa
- (
inicio de
sub-patrón
- )
fin de
sub-patrón
- ?
extiende el significado de (,
también es el cuantificador 0 ó 1 también
es el cuantificador de mÃnimo
- *
cuantificador cero o
más
- +
cuantificador uno o más
- {
cuantificador de inicio de valores
mÃnimo/máximo
- }
cuantificador de final de valores
mÃnimo/máximo
Un segmento de un patrón que se encuentre entre corchetes
cuadrados es llamado una "clase de caracteres". En una clase de
caracteres, los únicos meta-caracteres son:
- \
caracter general de
escape
- ^
niega la clase, pero sólo si se
trata del primer caracter
- -
indica un rango de
caracteres
- ]
finaliza la clase de
caracteres
Las secciones siguientes describen el uso de cada uno de los
meta-caracteres.
Barra Invertida
El caracter de barra invertida tiene varios usos. Primero, si es
seguido por un caracter no-alfanumérico, remueve cualquier
significado que el caracter pueda tener. Este uso de la barra
invertida como un caracter de escape se aplica tanto dentro como
fuera de las clases de caracteres.
Por ejemplo, si desea crear una coincidencia con un caracter "*",
debe escribir "\*" en el patrón. Esto es aplicable bien
sea que el caracter siguiente hubiese sido interpretado como un
meta-caracter o no, asà que siempre es seguro preceder un
caracter no-alfanumérico con "\" para indicar que se
representa a él mismo. En particular, si desea crear una
coincidencia con una barra invertida, escriba "\\".
Si un patrón es compilado con la opción PCRE_EXTENDED,
los espacios en blanco del patrón (fuera de una clase de
caracteres) y los caracteres entre un "#", fuera de una clase de
caracteres, y el siguiente salto de lÃnea son
ignorados. Una barra invertida de escape puede ser usada para
incluir un espacio en blanco o un caracter "#" como parte del
patrón.
Un segundo uso de la barra invertida ofrece una forma de
codificar caracteres no-imprimibles en los patrones de una forma
visible. No hay restricciones sobre la apariencia de los
caracteres no-imprimibles, aparte del cero binario que finaliza
un patrón, pero cuando un patrón está siendo
preparado mediante la edición de texto, usualmente es
más fácil usar una de las siguientes secuencias de
escape en lugar de los caracteres binarios que representan:
- \a
alarma, esto es, el caracter BEL
(hexadecimal 07)
- \cx
"control-x", en donde x es cualquier
caracter
- \e
escape (hexadecimal
1B)
- \f
alimentación de página
(hexadecimal 0C)
- \n
nueva lÃnea (hexadecimal
0A)
- \r
retorno de carro (hexadecimal
0D)
- \t
tabulador (hexadecimal
09)
- \xhh
caracter con código hexadecimal
hh
- \ddd
caracter con código octal ddd, o
referencia hacia atrás
El efecto preciso de "\cx" es como sigue: si
"x" es una letra minúscula, ésta
es convertida a mayúscula. Entonces el sexto bit del
caracter (40 en hexadecimal) es invertido. Por lo tanto,
"\cz" se convierte en 1A en hexadecimal, pero
"\c{" se convierte en 3B en hexadecimal,
mientras que "\c;" se convierte en 7B en
hexadecimal.
Después de "\x", son leidos hasta dos
dÃgitos hexadecimales (las letras pueden ser
mayúsculas o minúsculas). En modo
UTF-8, "\x{...}" es permitido, en
donde el contenido entre corchetes es una cadena de
dÃgitos hexadecimales. Es interpretado como un caracter
UTF-8 cuyo número de código es el número
hexadecimal dado. La secuencia de escape hexadecimal original,
\xhh, coincide con un caracter UTF-8 de dos
bytes si el valor es mayor que 127.
Después de "\0", son leÃdos
hasta dos dÃgitos octales más. En ambos casos, si
hay menos de dos dÃgitos, se usarán sólo los
que estén presentes. Por lo tanto, la secuencia
"\0\x\07" especifica dos ceros binarios
seguidos de un caracter BEL. Asegúrese de indicar dos
dÃgitos después del cero inicial si el caracter que
sigue es en sà un dÃgito octal.
La gestión de una barra invertida seguida por un
dÃgito diferente de cero es complicada. Por fuera de una
clase de caracteres, PCRE lee el dÃgito y cualquier otro
que le siga como un número decimal. Si el número es
menor que diez, o si han habido al menos tantos paréntesis
izquierdos de captura en la expresión, entonces la
secuencia entera es tomada como
una referencia
hacia atrás. Una descripción
de cómo trabaja esto es presentada más adelante,
tras la discusión sobre sub-patrones con
paréntesis.
Al interior de una clase de caracteres, o si el número
decimal es mayor que 9 y no han habido tantos sub-patrones de
captura, PCRE lee de nuevo hasta tres dÃgitos octales que
sigan a la barra invertida, y genera un byte sencillo a partir de
los ocho bits menos significativos del valor. Cualquier
dÃgito subsiguiente se representa a él mismo. Por
ejemplo:
- \040
es otro modo de escribir un
espacio
- \40
es lo mismo, siempre que haya menos de cuarenta sub-patrones
de captura previos
- \7
siempre es una referencia hacia
atrás
- \11
puede ser una referencia hacia atrás, u otra forma de
escribir un tabulador
- \011
siempre es un tabulador
- \0113
es un tabulador seguido del caracter
"3"
- \113
es el caracter con el código octal 113 (ya que no
puede haber más de 99 referencias hacia atrás)
- \377
es un byte que consiste completamente de
bits 1
- \81
puede ser una referencia hacia atrás, o un cero
binario seguido por los caracteres "8" y "1"
Note que los valores octales del 100 o números más
grandes no deben iniciar con un cero, ya que no se leen
más de tres dÃgitos octales.
Todas las secuencias que definen el valor de un byte sencillo
pueden ser usadas tanto dentro como fuera de las clases de
caracteres. Adicionalmente, la secuencia "\b"
es interpretada como el caracter backspace (hexadecimal 08) al
interior de una clase de caracteres. Por fuera de una clase de
caracteres tiene un significado diferente (ver más
adelante).
El tercer uso de la barra invertida es para especificar tipos
genéricos de caracteres:
- \d
cualquier dÃgito
decimal
- \D
cualquier caracter que no sea un
dÃgito decimal
- \s
cualquier caracter de espacio en
blanco
- \S
cualquier caracter que no sea un espacio en
blanco
- \w
cualquier caracter de
"palabra"
- \W
cualquier caracter que no sea de
"palabra"
Cada pareja de las secuencias de escape divide el conjunto global
de caracteres en dos grupos separados. Cualquier caracter dado
coincide con uno, y sólo uno, de cada pareja.
Un caracter de "palabra" es cualquier letra o dÃgito, o el
caracter de subrayado, esto quiere decir, cualquier caracter que
pueda ser parte de una "palabra" en Perl. La
definición de letras y dÃgitos es controlada por
las tablas de caracteres de PCRE, y puede variar si se
están efectuando coincidencias especÃficas a
localidades (vea "Soporte de localidades" más arriba). Por
ejemplo, en la localidad "fr" (Francia), algunos códigos
de caracteres mayores a 128 son usados para letras con acentos, y
éstas coinciden con \w.
Estas secuencias de tipos de caracter pueden aparecer tanto
dentro como fuera de las clases de caracteres. Cada una coincide
con un caracter del tipo apropiado. Si el punto de coincidencia
actual es el final de la cadena de asunto, todas las secuencias
fallan, ya que no hay caracteres a coincidir.
El cuarto uso de la barra invertida es para ciertas aserciones
simples. Una aserción especifica una condición que
tiene que cumplirse en un punto particular de una coincidencia,
sin consumir caracter alguno de la cadena de asunto. El uso de
sub-patrones para aserciones más complicadas se describe
más adelante. Las aserciones de barra invertida son
- \b
lÃmite de
palabra
- \B
no-lÃmite de
palabra
- \A
inicio de la cadena de asunto (independiente
del modo multilÃnea)
- \Z
fin de la cadena de asunto o una nueva lÃnea al final
(independiente del modo multilÃnea)
- \z
fin de la cadena de asunto (independiente
del modo multilÃnea)
- \G
primera posición de coincidencia en
el asunto
Estas aserciones no pueden aparecer dentro de clases de
caracteres (pero note que "\b" tiene un
significado diferente, el cual es el caracter backspace, dentro
de una clase de caracteres).
Un lÃmite de palabra es una posición en la cadena
de asunto en donde el caracter actual y el anterior no coinciden
ambos con \w o \W (es
decir, uno coincide con \w y el otro coincide
con \W), o se puede tratar del principio o el
final de la cadena, si el primer o último caracter
coincide con \w, respectivamente.
Las aserciones \A, \Z, y
\z se diferencian de los caracteres
tradicionales circunflejo y dólar (descritos más
adelante) en que las primeras sólo coinciden al inicio y
final absolutos de la cadena de asunto, independientemente de las
opciones definidas. No son influenciadas por las opciones PCRE_MULTILINE
o PCRE_DOLLAR_ENDONLY. La
diferencia entre \Z y \z es
que \Z coincide antes de una nueva
lÃnea que sea el último caracter de la cadena como
también al final de la cadena, mientas que
\z sólo coincide al final.
La aserción \G es cierta
únicamente cuando la posición de coincidencia
actual está en el punto de inicio de la coincidencia,
como se especifica por el argumento
desplazamiento de
preg_match(). Difiere de
\A cuando el valor de
desplazamiento es diferente de cero. Se
encuentra disponible desde PHP 4.3.3.
Es posible usar \Q y \E
para ignorar meta-caracteres de expresiones regulares en el
patrón desde PHP 4.3.3. Por ejemplo:
\w+\Q.$.\E$ coincidirá con uno o
más caracteres de palabra, seguido por los literales
.$. y anclado al final de la cadena.
Propiedades de caracter Unicode
A partir de PHP 4.4.0 y 5.1.0 se encuentran disponibles tres
secuencias de escape adicionales para comparar tipos de caracter
genéricos cuando el modo UTF-8 es
seleccionado. Éstos son:
- \p{xx}
un caracter con la propiedad
xx
- \P{xx}
un caracter sin la propiedad
xx
- \X
una secuencia Unicode
extendida
Los nombres de propiedad representados por xx
en la lista anterior están limitados a las propiedades de
categorÃa general Unicode. Cada caracter tiene
exactamente una propiedad de aquéllas, especificada por
una abreviación de dos letras. Para compatibilidad con
Perl, es posible especificar la negación incluyendo un
circunflejo entre el corchete de apertura y el nombre de
propiedad. Por ejemplo, \p{^Lu} es lo mismo
que \P{Lu}.
Si solo una letra es especificada con \p o
\P, ella incluye todas las propiedades que
comienzan con esa letra. En este caso, en la ausencia de la
negación, los corchetes en la secuencia de escape son
opcionales; los siguientes dos ejemplos tienen el mismo efecto:
\p{L}
\pL
Tabla 1. Códigos de propiedad soportados
| C | Otro |
| Cc | Control |
| Cf | Formato |
| Cn | Sin asignar |
| Co | Uso privado |
| Cs | Sustituto |
| L | Letra |
| Ll | Letra minúscula |
| Lm | Letra modificadora |
| Lo | Otra letra |
| Lt | Letra de tÃtulo |
| Lu | Letra mayúscula |
| M | Marca |
| Mc | Marca de espacio |
| Me | Marca de clausura |
| Mn | Marca
diferente de espacio |
| N | Número |
| Nd | Número decimal |
| Nl | Número de letra |
| No | Otro número |
| P | Puntuación |
| Pc | Puntuación conector |
| Pd | Puntuación
de raya |
| Pe | Putuación de cierre |
| Pf | Puntuación final |
| Pi | Puntuación inicial |
| Po | Otra puntuación |
| Ps | Puntuación
de apertura |
| S | SÃmbolo |
| Sc | SÃmbolo de moneda |
| Sk | SÃmbolo modificador |
| Sm | SÃmbolo matemático |
| So | Otro sÃmbolo |
| Z | Separador |
| Zl | Separador de lÃnea |
| Zp | Separador de párrafo |
| Zs | Separador de espacio |
Propiedades extendidas como "Greek" o "InMusicalSymbols" no son
soportadas por PCRE.
Especificar coincidencias no sensibles a
mayúsculas/minúsculas no afecta estas secuencias
de escape. Por ejemplo, \p{Lu} siempre
coincide únicamente con letras mayúsculas.
El escape \X coincide con cualquier
número de caracteres Unicode que formen una secuencia
Unicode extendida. \X es equivalente a
(?>\PM\pM*).
Es decir, coincide con un caracter sin la propiedad "marca",
seguido de cero o más caracteres con la propiedad
"marca", y trata la secuencia como un grupo atómico (vea
más adelante). Los caracteres con la propiedad "marca"
usualmente son acentos que afectan el caracter precedente.
Encontrar coincidencias por propiedades Unicode no es
rápido, ya que PCRE tiene que buscar una estructura que
contiene datos para más de quince-mil caracteres. Por
ello es que las secuencias de escape tradicionales como
\d y \w no usan
propiedades Unicode en PCRE.
El circunflejo y el dólar
Por fuera de una clase de caracteres, en el modo predeterminado
de coincidencia, el caracter circunflejo es una aserción
que sólo es verdadera si el punto de coincidencia actual
es el inicio de la cadena de asunto. Al interior de una clase de
caracteres, el circunflejo tiene un significado completamente
distinto (ver más adelante).
El circunflejo no necesita ser el primer caracter del
patrón si se involucra un número de alternativas,
pero debe ser la primer cosa en cada alternativa en la que
aparezca si se espera que el patrón coincida con esa
rama. Si todas las alternativas posibles empiezan con un
circunflejo, esto es, si el patrón está limitado a
coincidir sólo con en el inicio del asunto, se dice que
es un patrón "anclado". (También hay otras
construcciones que pueden hacer que un patrón sea
anclado.)
Un caracter de dólar es una aserción que es
verdadera sólo si el punto de coincidencia actual se
encuentra al final de la cadena de asunto, o inmediatamente
antes de un caracter de nueva lÃnea que sea el
último caracter en la cadena (por defecto). El
dólar no necesita ser el último caracter del
patrón si hay varias alternativas involucradas, pero debe
ser el último elemento en cada rama en la que
aparezca. El dólar no tiene un significado especial en
una clase de caracteres.
El significado del dólar puede ser modificado para que
coincida sólo al final absoluto de la cadena, definiendo
la opción PCRE_DOLLAR_ENDONLY
en tiempo de compilación o a la hora de efectuar la
comparación. Esto no afecta a la aserción \Z.
Los significados de los caracteres circunflejo y dólar
son modificados si la opción PCRE_MULTILINE
es definida. Cuando éste es el caso, éstos
caracteres coinciden inmediatamente antes e inmediatamente
después de un caracter "\n" interno, respectivamente,
además de coincidir con el inicio y el final de la cadena
de asunto. Por ejemplo, el patrón /^abc$/ coincide con la
cadena de asunto "def\nabc" en modo multilÃnea, pero no
en otro caso. Consecuentemente, los patrones que son anclados en
modo de lÃnea sencilla ya que todas las ramas empiezan
con "^" no son anclados en modo multilÃnea. La
opción PCRE_DOLLAR_ENDONLY
es ignorada si PCRE_MULTILINE
es definido.
Tenga en cuenta que las secuencias \A, \Z y \z pueden ser usadas
para coincidir con el inicio y el final del asunto en ambos
modos, y si todas las ramas de un patrón comienzan con
\A, el patrón siempre es anclado, independientemente de
si PCRE_MULTILINE
es definido o no.
Punto
Por fuera de una clase de caracteres, un punto en el
patrón coincide con cualquier caracter del asunto,
incluyendo caracteres no-imprimibles, pero no el salto de
lÃnea (por defecto). Si la opción PCRE_DOTALL es
definida, entonces los puntos coinciden con los saltos de
lÃnea también. El manejo del punto es
completamente independiente del uso del circunflejo y el
dólar, dado que la única relación entre
ellos es que ambos casos involucran caracteres de nueva
lÃnea. El punto no tiene un significado especial dentro
de una clase de caracteres.
Es posible usar \C para coincidir con un
byte sencillo. Tiene sentido en modo UTF-8
en donde el punto coincide con el caracter completo que puede
consistir de múltiples bytes.
Corchetes cuadrados
Un corchete cuadrado de apertura inicia una clase de caracteres,
terminada por un corchete cuadrado de cierre. Un corchete
cuadrado de cierre por sà solo no es especial. Si un
corchete cuadrado de cierre es requerido como un miembro de la
clase, deberÃa ser el primer caracter de datos en la
clase (después de un circunflejo inicial, si está
presente) o escapado con una barra invertida.
Una clase de caracteres coincide con un caracter único en
el asunto; el caracter debe estar en el conjunto de los
caracteres definidos por la clase, a menos que el primer
caracter en la clase sea un circunflejo, en cuyo caso el
caracter del asunto no debe estar en el conjunto definido por la
clase. Si un circunflejo es necesitado realmente como un miembro
de la clase, asegúrese de que no sea el primer caracter,
o escápelo con una barra invertida.
Por ejemplo, la clase de caracteres [aeiou] coincide con
cualquier vocal minúscula, mientras que [^aeiou] coincide
con cualquier caracter que no sea una vocal minúscula.
Note que un circunflejo es una notación conveniente para
especificar los caracteres que están en la clase
enumerando aquellos que no lo están. No es una
aserción: aun consume un caracter de la cadena de asunto,
y falla si el apuntador actual está al final de la
cadena.
Cuando se recurre a las comparaciones insensibles a
mayúsculas y minúsculas, cualquier letra en una
clase representa ambas versiones, por ejemplo, un patrón
insensible a mayúsculas y minúsculas [aeiou]
coincide tanto con "A" como con "a", y un patrón
insensible a mayúsculas y minúsculas [^aeiou] no
coincide con "A", mientras que una versión sensible lo
harÃa.
El caracter de nueva lÃnea nunca es tratado de un modo
especial entra las clases de caracteres, independientemente de
los valores de las opciones PCRE_DOTALL o
PCRE_MULTILINE. Una
clase como [^a] siempre coincidirá con una nueva
lÃnea.
El caracter menos (guión) puede ser usado para
especificar un rango de caracteres en una clase de
caracteres. Por ejemplo, [d-m] coincide con cualquier letra
entre d y m, ambas inclusive. Si un caracter menos es requerido
en una clase, debe ser escapado con una barra invertida, o
aparecer en una posición en donde no pueda ser
interpretado como indicador de rango, normalmente como primer o
último caracter de la clase.
No es posible tener el caracter literal "]" como el caracter
final de un rango. Un patrón como [W-]46] es
interpretado como una clase de dos caracteres ("W" y "-")
seguida por la cadena literal "46]", asà que
coincidirÃa con "W46]" o "-46]". Sin embargo, si el
caracter "]" es escapado con una barra invertida, éste es
interpretado como el final del rango, asà que [W-\]46] es
interpretado como una clase única que contiene un rango
seguido por dos caracteres diferentes. La representación
octal o hexadecimal de "]" puede ser usada también para
finalizar un rango.
Los rangos trabajan en el orden de la secuencia ASCII. Pueden
ser usados también para caracteres especificados
numéricamente, por ejemplo [\000-\037]. Si un rango que
incluye letras es usado cuando es definida la comparación
insensible a mayúsculas y minúsculas, el rango
coincide las letras en cualquiera de los casos. Por ejemplo,
[W-c] es equivalente a [][\^_`wxyzabc], efectuando la
coincidencia insensible a mayúsculas y minúsculas,
y si las tablas de caracteres para la localidad "fr"
están en uso, entonces [\xc8-\xcb] coincide con los
caracteres E acentuados en ambos casos.
Los tipos de caracteres \d, \D, \s, \S, \w, y \W también
pueden aparecer en una clase de caracteres, y añaden los
caracteres que ellos representan a la clase. Por ejemplo,
[\dABCDEF] coincide con cualquier dÃgito hexadecimal. Un
circunflejo puede ser convenientemente usado con los tipos de
caracter en mayúscula para especificar un conjunto
más restringido de caracteres que el de una
comparación con tipo en minúscula. Por ejemplo, la
clase [^\W_] coincide con cualquier letra o dÃgito, pero
no con el signo de subrayado.
Todos los caracteres no-alfanuméricos diferentes a \, -,
^ (al comienzo) y el caracter ] de cierre no tienen un
significado especial en una clase de caracteres, pero no hace
daño que se encuentren escapados..
Barra vertical
Los caracteres de barra vertical son usados para separar
patrones alternativos. Por ejemplo, el patrón
gilbert|sullivan coincide o bien con
"gilbert" o con "sullivan". Puede usarse cualquier número
de alternativas, y se permiten alternativas vacÃas (que
coinciden con la cadena vacÃa). El proceso de
comparación prueba con cada alternativa de izquierda a
derecha, y la primera que tenga éxito es usada. Si las
alternativas están al interior de un sub-patrón
(definido más adelante), el "éxito" quiere decir
que coincida con el resto del patrón principal como
también con la alternativa en el sub-patrón.
Definición de opciones internas
Los valores de PCRE_CASELESS,
PCRE_MULTILINE,
PCRE_DOTALL,
PCRE_UNGREEDY,
PCRE_EXTRA,
y PCRE_EXTENDED
pueden ser modificados desde el interior del patrón por
una secuencia de letras de opciones de Perl encerradas entre
"(?" y ")". Las letras de opciones son:
Tabla 2. Letras de opciones internas
Por ejemplo, (?im) define una comparación insensible a
mayúsculas y minúsculas y en modo
multilÃnea. También es posible eliminar
éstas opciones precediendo las letras con un
guión, asà como se permite también una
combinación de activaciones y desactivaciones como
(?im-sx), la cual define PCRE_CASELESS
y PCRE_MULTILINE
al mismo tiempo que desactiva PCRE_DOTALL y
PCRE_EXTENDED. Si
una letra aparece antes y después del guión, la
opción será desactivada.
Cuando un cambio de opción ocurre en el nivel superior
(es decir, no al interior de los paréntesis de
sub-patrones), el cambio se aplica al resto del patrón a
seguir. Asà que /ab(?i)c/ coincide
únicamente con "abc" y "abC". Este comportamiento ha
cambiado en PCRE 4.0, el cual es distribuido desde PHP
4.3.3. Antes de aquellas versiones, /ab(?i)c/
actuarÃa como /abc/i
(p.ej. coincidiendo "ABC" y "aBc").
Si un cambio de opción sucede dentro de un
sub-patrón, el efecto es diferente. Este es un cambio
respecto a la conducta de Perl 5.005. Un cambio de opción
dentro de un sub-patrón afecta sólo a la parte del
sub-patrón que lo sigue, de modo que
(a(?i)b)c
coincide con abc y aBc y ninguna otra cadena (asumiendo que no
se está usando PCRE_CASELESS). De
esta forma, las opciones pueden definirse para tener diferentes
significados en diferente partes del patrón. Cualquier
cambio realizado en una alternativa ciertamente se aplica a
ramas subsecuentes al interior del mismo sub-patrón. Por
ejemplo,
(a(?i)b|c)
coincide con "ab", "aB", "c", y "C", aun cuando al coincidir con
"C", la primera rama es abandonada antes de definir la
opción. Esto es porque los efectos de definir de opciones
ocurren en tiempo de compilación. De otro modo,
ocurrirÃa un comportamiento muy extraño.
Las opciones especÃficas de PCRE PCRE_UNGREEDY
y PCRE_EXTRA
pueden ser modificadas del mismo modo que las opciones
compatibles con Perl usando los caracteres U y X
respectivamente. La opción bandera (?X) es especial en el
sentido en que siempre debe ocurrir antes que cualquier otra
caracterÃstica adicional que active en el patrón,
incluso cuando es definida en el nivel superior. Su mejor
ubicación es el inicio.
Sub-patrones
Los sub-patrones son delimitados por paréntesis, y pueden
estar anidados. Marcar parte de un patrón como un
sub-patrón logra dos cosas:
1. Ubica un conjunto de alternativas. Por ejemplo, el
patrón
cat(aract|erpillar|)
coincide con una de las palabras "cat", "cataract", o
"caterpillar". Sin los paréntesis, coincidirÃa con
"cataract", "erpillar" o la cadena vacÃa.
2. Define el sub-patrón como un sub-patrón de
captura (como se definió anteriormente). Cuando el
patrón completo coincida, esa porción de la cadena
de asunto que coincidió con el sub-patrón es
devuelta al origen mediante el
argumento ovector
de pcre_exec(). Los paréntesis de
apertura son contados de izquierda a derecha (empezando desde 1)
para obtener los números de los sub-patrones de captura.
Por ejemplo, si la cadena "the red king" es comparada contra el
patrón
the ((red|white) (king|queen))
las sub-cadenas capturadas son "red king", "red", y "king", y son
numeradas como 1, 2 y 3.
El hecho de que los simples paréntesis realicen dos
funciones no siempre es útil. Con frecuencia se presenta
el caso en el que un sub-patrón de agrupamiento es
requerido sin necesidad de una captura. Si un paréntesis
de apertura es seguido por "?:", el sub-patrón no realiza
ninguna captura, y no es contado cuando se compute el
número de sub-patrones subsiguientes capturados. Por
ejemplo, si la cadena "the white queen" es comparada con el
patrón
the ((?:red|white) (king|queen))
las sub-cadenas capturadas son "white queen" y "queen", y son
numeradas como 1 y 2. El número máximo de
sub-cadenas capturadas es de 99, y el número máximo
de todos los sub-patrones, de captura o no, es de 200.
Como un atajo conveniente, si cualquiera de las opciones se
requiere al inicio de un sub-patrón que no sea de captura,
las letras de las opciones pueden aparecer entre los caracteres
"?" y ":". Por lo tanto, los dos patrones
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
coinciden con exactamente el mismo conjunto de cadenas. Dado que
las ramas alternativas son probadas de izquierda a derecha, y las
opciones no son reestablecidas hasta el final del
sub-patrón, una definición de opción en una
rama afecta las ramas subsecuentes, asà que los patrones
anteriores coinciden con "SUNDAY", al igual que con "Saturday".
Es posible nombrer el sub-patrón con
(?P<nombre>patron) a partir de PHP
4.3.3. En ese caso, las matrices con coincidencias
contendrán el resultado indexado por la cadena junto con
el resultado indexado por un número.
Repetición
La repetición es especificada por cuantificadores, los
cuales pueden ir tras cualquiera de los siguientes elementos:
un caracter sencillo, posiblemente
escapado
el meta-caracter .
una clase de caracteres
una referencia hacia atrás (vea la
siguiente sección)
un sub-patrón entre paréntesis
(a menos que se trate de una aserción - vea más
adelante)
El cuantificador general de repetición indica un
número mÃnimo y un número máximo de
coincidencias permitidas, dando los dos números entre
corchetes ondulados (llaves), separados por una coma. Los
números deben ser menores a 65536, y el primero debe ser
menor o igual al segundo. Por ejemplo:
z{2,4}
coincide con "zz", "zzz", o "zzzz". Una llave de cierre por
sà sola no es un caracter especial. Si el segundo
número es omitido, pero aparece la coma, entonces no hay
lÃmite superior; si el segundo número y la coma son
omitidos ambos, el cuantificador indica el número exacto
de repeticiones requeridas. Por lo tanto
[aeiou]{3,}
coincide con al menos 3 vocales sucesivas, pero podrÃa
coincidir con muchas más, mientras que
\d{8}
coincide con exactamente ocho dÃgitos. Una llave de
apertura que aparezca en una posición en donde no se
permite un cuantificador, o una que no coincida con la sintaxis
de un cuantificador, es tomada como un caracter literal. Por
ejemplo, {,6} no es un cuantificador, sino una cadena literal de
cuatro caracteres.
Se permite el uso del cuantificador {0}, lo que provoca que la
expresión se comporte como si el elemento anterior y el
cuantificador no estuvieran presentes.
Por conveniencia (y compatibilidad histórica) los tres
cuantificadores más comunes tienen abreviaciones de un
solo caracter:
Tabla 3. Cuantificadores de caracter-único
| * | equivalente a {0,} |
| + | equivalente a {1,} |
| ? | equivalente a {0,1} |
Es posible construir ciclos infinitos mediante un
sub-patrón que no pueda coincidar con ningún
caracter con un cuantificador que no tenga lÃmite
superior, por ejemplo:
(a?)*
Las primeras versiones de Perl y PCRE solÃan producir un
error en tiempo de compilación para tales patrones. Sin
embargo, dado que existen casos en donde esto puede ser
útil, tales patrones son aceptados ahora, pero si
cualquier repetición del sub-patrón no coincide
realmente con ningún caracter, el ciclo es interrumpido a
la fuerza.
Por defecto, los cuantificadores son "ambiciosos", lo que quiere
decir, coinciden con tanto material como les es posible (hasta el
número máximo de veces permitido), sin provocar que
el resto del patrón falle. El ejemplo clásico en el
que esto causa problema es a la hora de crear coincidencias con
comentarios en programas en C. Éstos aparecen entre las
secuencias /* y */ y, al interior de la secuencia, los caracteres
* y / pueden aparecer individualmente. Un intento por coincidir
comentarios en C al aplicar el patrón
/\*.*\*/
sobre la cadena
/* primer comentario */ no comentado /* segundo
comentario */
falla, ya que coincide con la cadena entera debido a la
ambición del elemento .*
Sin embargo, si un cuantificador es seguido por un signo de
interrogación, entonces deja de ser ambicioso, y en su
lugar coincide el mÃnimo número de veces posibles,
de tal suerte que el patrón
/\*.*?\*/
hace lo correcto con los comentarios en C. El significado de los
varios cuantificadores no se modifica en otro modo, tan
sólo el número preferido de coincidencias. No
confunda éste uso del signo de interrogación con su
uso como un cuantificador por sà solo. Debido a que tiene
dos usos, a veces puede aparecer dos veces seguidas, como en
\d??\d
caso que coincide con un dÃgito de ser posible, pero puede
coincidir con dos si ese el único modo en que el resto del
patrón coincida.
Si se encuentra definida la opción PCRE_UNGREEDY
(la cual no está disponible en Perl) entonces los
cuantificadores no son ambiciosos por defecto, pero cada uno por
separado puede serlo cuando a continuación de ellos se
encuentra un signo de interrogación. En otras palabras,
invierte el comportamiento predeterminada.
Los cuantificadores seguidos por + son
"posesivos". Ellos consumen tantos caracteres como es posible y
no regresan para coincidir con el resto del patrón. Por lo
tanto .*abc coincide con "aabc" pero
.*+abc no ya que .*+
consume la cadena completa. Los cuantificadores posesivos pueden
ser usados para incrementar la rapidez de procesamiento desde PHP
4.3.3.
Cuando un sub-patrón entre paréntesis es
cuantificado con un número mÃnimo de repeticiones
superior a 1 o con un lÃmite máximo, se necesita
mayor almacenamiento para el patrón compilado, en
proporción al tamaño del mÃnimo o del
máximo.
Si un patrón empieza con .* o .{0,} y la opción
PCRE_DOTALL
(equivalente a /s en Perl) es definida, permitiendo de esa forma
que . coincida con nuevas lÃneas, entonces el
patrón es anclado implÃcitamente, ya que cualquier
cosa a continuación será comparada contra cada
posición de caracter en la cadena de asunto, asÃ
que no hay razones para reintentar la coincidencia en su
totalidad en cualquier posición luego de la primera. PCRE
trata tales patrones como si estuvieran precedidos por \A. En los
casos donde se conoce que la cadena de asunto no contiene nuevas
lÃneas, vale la pena definir PCRE_DOTALL
cuando el patrón comienza con .* para obtener esta
optimización, o alternativamente usar ^ para indicar el
anclamiento explÃcitamente.
Cuando un sub-patrón de captura es repetido, el valor
capturado es la sub-cadena que coincidió con la
iteración final. Por ejemplo, luego de que
(tweedle[dume]{3}\s*)+
ha coincidido con "tweedledum tweedledee" el valor de la
sub-cadena capturada es "tweedledee". Sin embargo, si hay
sub-patrones de captura anidados, los valores capturados
correspondientes pueden haber sido definidos en las iteraciones
anteriores. Por ejemplo, después de que
/(a|(b))+/
coincide con "aba", el valor de la segunda sub-cadena capturada
es "b".
Referencias hacia atrás
Por fuera de una clase de caracteres, una barra invertida seguida
por un digito mayor que cero (y posiblemente más
dÃgitos) es una referencia hacia atrás a un
sub-patrón de captura anterior (es decir, a su izquierda)
en el patrón, siempre y cuando existan tantos
paréntesis izquierdos de captura.
Sin embargo, si el número decimal a continuación de
la barra invertida es menor que diez, siempre es tomado como una
referencia hacia atrás, y causa un error sólo si no
hay los suficientes paréntesis izquierdos de captura en
todo el patrón. En otras palabras, los paréntesis
que son referidos no necesitan estar a la izquierda de la
referencia para números menores que diez. Vea la
sección anterior titulada "Barra invertida" para
más detalles sobre el manejo de los dÃgitos que
siguen a una barra invertida.
Una referencia hacia atrás coincide con cualquier cosa que
haya coincidido realmente con el sub-patrón de captura en
la cadena de asunto actual, en lugar de hacerlo con cualquier
cosa que coincida con el sub-patrón mismo. De modo que el
patrón
(sens|respons)e and \1ibility
coincide con "sense and sensibility" y "response and
responsibility", pero no "sense and responsibility". Si se
está aplicando una comparación sensible a
mayúsculas y minúsculas al momento de la referencia
hacia atrás, entonces la distinción de las letras
es importante. Por ejemplo,
((?i)rah)\s+\1
coincide con "rah rah" y "RAH RAH", pero no "RAH rah", incluso
cuando el sub-patrón de captura original fue comparado de
forma insensible a mayúsculas y minúsculas.
Puede haber más de una referencia hacia atrás hacia
el mismo sub-patrón. Si un sub-patrón no ha sido
usado realmente en una coincidencia particular, entonces
cualquier referencia hacia atrás hacia aquél
siempre falla. Por ejemplo, el patrón
(a|(bc))\2
siempre falla si comienza coincidiendo con "a" en lugar de
"bc". Ya que puede haber hasta 99 referencias hacia atrás,
todos los dÃgitos que siguen a la barra invertida son
tomados como parte de un potencial número de referencia
hacia atrás. Si el patrón continúa con un
caracter de dÃgito, entonces debe ser usado algún
delimitador para terminar la referencia hacia atrás. Si la
opción PCRE_EXTENDED
es definida, este puede ser el espacio en blanco. De otro modo,
un comentario vació puede ser usado.
Una referencia hacia atrás que ocurra dentro del
paréntesis al cual hace referencia falla cuando el
sub-patrón es usado por primera vez, asà que, por
ejemplo, (a\1) nunca crea coincidencias. Sin embargo, tales
referencia pueden ser útiles al interior de sub-patrones
repetidos. Por ejemplo, el patrón
(a|b\1)+
coincide con cualquier número de "a"s y también con
"aba", "ababaa" etc. Para cada iteración del
sub-patrón, la referencia hacia atrás 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 hacia atrás. Esto puede lograrse usando
alternaciones, como en el ejemplo anterior, o por medio de un
cuantificador con un mÃnimo de cero.
Aserciones
Una aserción es una prueba sobre los caracteres a
continuación o antes del punto actual de coincidencia que
no consume caracteres en realidad. Las aserciones simples
codificadas como \b, \B, \A, \Z, \z, ^ y $ son descritas
anteriormente. Las aserciones más complicadas son
codificadas como sub-patrones. Hay dos tipos: aquellas que
trabajan con material más adelante de la posición
actual en la cadena de asunto y aquellas que lo hacen con
material hacia atrás.
Un sub-patrón de aserción es comparado del modo
usual, excepto que no causa que el punto actual de coincidencia
cambie. Las aserciones hacia adelante comienzan con (?= en el
caso de aserciones positivas y (?! para las negativas. Por
ejemplo,
\w+(?=;)
coincide con una palabra seguida por un punto-y-coma. pero no
incluye el punto-y-coma en la coincidencia, y
foo(?!bar)
coincide con cualquier ocurrencia de "foo" que no sea seguida por
"bar". Note que el patrón, en apariencia semejante,
(?!foo)bar
no encuentra una ocurrencia de "bar" que sea precedida por algo
diferente de "foo"; encuentra cualquier ocurrencia de "bar", ya
que la aserción (?!foo) es siempre verdadera cuando los
siguientes tres caracteres son "bar". Una aserción hacia
atrás es necesaria para conseguir este efecto.
Las aserciones hacia atrás comienzan con (?<= para las
aserciones positivas y (?<! para las negativas. Por ejemplo,
(?<!foo)bar
encuentra una ocurrencia de "bar" que no es precedida por "foo".
Los contenidos de una aserción hacia atrás son
restringidos de tal forma que todas las cadenas con las que
coinciden deben tener una longitud fija. Sin embargo, si hay
varias alternativas, no todas tienen que tener la misma
longitud. Por lo tanto
(?<=bullock|donkey)
se permite, pero
(?<!dogs?|cats?)
genera un error en tiempo de compilación. Las ramas que
coinciden con cadenas de diferentes longitudes son permitidas
sólo en el nivel superior de la aserción hacia
atrás. Ésta es una extensión en
comparación con Perl 5.005, en donde se requiere que todas
las ramas coincidan con la misma longitud de cadena. Una
aserción como
(?<=ab(c|de))
no es permitida, ya que su rama única de nivel superior
puede coincidir con dos longitudes diferentes, pero es aceptable
si se reescribe para usar dos ramas de nivel superior:
(?<=abc|abde)
La implementación de las aserciones hacia atrás
consiste en, para cada alternativa, mover temporalmente la
posición actual hacia atrás en el ancho fijo e
intentar la coincidencia. Si no hay suficientes caracteres antes
de la posición actual, la coincidencia está
destinada a fallar. Las aserciones hacia atrás, en
unión con los sub-patrones de una sola aplicación,
pueden ser particularmente útiles para las coincidencias
al final de cadenas; un ejemplo es dado al final de la
sección sobre sub-patrones de una aplicación.
Varias aserciones (de cualquier tipo) pueden ocurrir en
sucesión. Por ejemplo,
(?<=\d{3})(?<!999)foo
coincide con "foo" precedido de tres dÃgitos que no sean
"999". Note que cada una de las aserciones es aplicada
independientemente en el mismo punto en la cadena de
asunto. Primero hay un chequeo para que los tres caracteres
previos sean todos dÃgitos, luego hay un chequeo para que
los mismos caracteres no sean "999". Este patrón no
coincide con "foo" precedido de seis caracteres, en donde los
primeros son dÃgitos y los últimos tres no son
"999". Por ejemplo, no coincide con "123abcfoo". Un patrón
para conseguir eso es
(?<=\d{3}...)(?<!999)foo
En este caso la primera aserción revisa los seis
caracteres anteriores, y chequea que los tres primeros sean
dÃgitos, y luego la segunda aserción chequea que
los tres caracteres anteriores no sean "999".
Las aserciones puede ser anidadas en cualquier
combinación. Por ejemplo,
(?<=(?<!foo)bar)baz
coincide con una ocurrencia de "baz" que sea precedida por "bar",
la cual a su vez no sea precedida por "foo", mientras que
(?<=\d{3}...(?<!999))foo
es otro patrón que coincide con "foo" precedido por tres
dÃgitos y tres caracteres cualquiera que no sean "999".
Los sub-patrones de aserción no son sub-patrones de
captura, y no pueden ser repetidos, ya que no tiene sentido
afirmar la misma cosa varias veces. Si una aserción de
cualquier tipo contiene sub-patrones de captura en su interior,
éstos son contados con el propósito de numerar los
sub-patrones de captura en todo el patrón. Sin embargo, la
captura de subcadenas solo se lleva a cabo en las aserciones
positivas, porque no tiene sentido para las negativas.
Las aserciones cuentan para el máximo de 200 sub-patrones
entre paréntesis.
Sub-patrones de una sola aplicación
Tanto con las repeticiones máximas como en las
mÃnimas, el hecho de que falle de lo que se encuentra a
continuación causa por lo general que el item repetido
sea re-evaluado para ver si un número diferente de
repeticiones permite que el resto del patrón coincida. A
veces es útil prevenir esto, ya sea cambiando la
naturaleza de la coincidencia, o causando que falle antes de
cuando ocurrirÃa de otra forma, cuando el creador del
patrón sabe que no tiene sentido continuar.
Considere, por ejemplo, el patrón \d+foo cuando se aplica
a la lÃnea de asunto
123456bar
Después de coincidir con los seis dÃgitos y fallar
al comparar con "foo", la acción normal del motor es
intentar otra vez con sólo cinco dÃgitos para
coincidir con \d+, y luego con cuatro, y asÃ
sucesivamente, antes de fallar por completo. Los sub-patrones de
una aplicación ofrecen el medio de especificar que una vez
una porción del patrón ha coincidido, no debe ser
re-evaluada en esta manera, asà que el motor se
rendirÃa inmediamente al fallar su intento por coincidir
con "foo" la primera vez. La notación es otra forma
especial de paréntesis, iniciado con (?> como en este
ejemplo:
(?>\d+)bar
Este tipo de paréntesis "bloquea" la parte del
patrón que contiene una vez ha coincidido, y se previene
que un fallo más al interior del patrón retroceda
al punto original. El retroceso hacia elementos previos funciona
normalmente, después de todo.
Una descripción alternativa es que un sub-patrón de
este tipo coincide con la cadena de carecteres que un
patrón independiente idéntico coincidirÃa,
si estuviera anclado en el punto actual de la cadena de asunto.
Los sub-patrones de una sola aplicación no son
sub-patrones de captura. Los casos simples como el ejemplo
anterior pueden verse como una repetición máxima
que debe tragar todo lo que pueda. Asà que, mientras que
tanto \d+ como \d? están preparados para ajustar el
número de dÃgitos con los que coinciden para hacer
que el resto del patrón coincida, (?>\d+) puede
coincidir sólo con un secuencia enteramente de
dÃgitos.
Esta construcción puede, por supuesto, contener
sub-patrones arbitrariamente complicados, y pueden estar
anidados.
Los sub-patrones de una aplicación pueden ser usados en
unión con aserciones hacia atrás para especificar
coincidencias eficientes al final de la cadena de asunto.
Considere un patrón sencillo como
abcd$
cuando se aplica a una cadena larga con la cual no coincide. Dado
que la comparación se realiza de izquierda a derecha, PCRE
buscará cada "a" en el asunto y luego verá si lo
que sigue coincide con el resto del patrón. Si el
patrón se especifica como
^.*abcd$
entonces el segmento .* inicial coincide con la cadena entera
primero, pero cuando esto falle (ya que no habrá una "a" a
continuación), retrocede para coincidir con todo menos el
último caracter, luego con todo excepto los dos
últimos y asà sucesivamente. Una vez más, la
búsqueda de "a" cubre la cadena completa, de derecha a
izquierda, asà que no hemos mejorado. Sin embargo, si el
patrón se escribiese como
^(?>.*)(?<=abcd)
entonces no hay retroceso para el elemento .*; sólo puede
coincidir con la cadena entera. La aserción hacia
atrás subsiguiente realiza una prueba única sobre
los últimos cuatro caracteres. Si falla, la coincidencia
falla inmediatamente. Para cadena largas, este enfoque representa
una diferencia significativa en el tiempo de procesamiento.
Cuando un patrón contiene una repetición ilimitada
al interior de un sub-patrón que puede ser por sÃ
mismo repetido un número ilimitado de veces, el uso de un
sub-patrón de una aplicación es la única
forma de evitar algunas coincidencias fallidas que consumen
ciertamente un tiempo muy largo. El patrón
(\D+|<\d+>)*[!?]
coincide con un número ilimitado de subcadenas que
consisten ya sea de no-dÃgitos, o dÃgitos entre
<>, seguidos por ! o ?. Cuando coincida, se ejecuta
rápido. Sin embargo, si se aplica sobre
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
toma un largo tiempo antes de reportar el fallo. Esto es porque
la cadena puede ser dividida entre las dos repeticiones en un
gran número de formas, y todas deben ser probadas. (El
ejemplo usó [!?] en lugar de un caracter sencillo al
final, ya que tanto PCRE como Perl cuentan con una
optimización que permite reportar fallos
rápidamente cuando un caracter sencillo es
usado. Recuerdan el último caracter simple que es
requerido para una coincidencia, y falla tempranamente si no
está presente en la cadena.) Si el patrón es
modificado a
((?>\D+)|<\d+>)*[!?]
las secuencias de no-dÃgitos no pueden ser interrumpidas,
y la falla ocurre rápidamente.
Sub-patrones condicionales
Es posible hacer que el proceso de comparación obedezca a
un sub-patrón condicionalmente o que elija entre dos
sub-patrones alternativos, dependiendo del resultado de una
aserción, o de si un sub-patrón de captura previo
coincidió o no. Las dos formas posibles de sub-patrones
condicionales son:
(?(condición)patrón-si)
(?(condición)patrón-si|patrón-no)
Si la condición es satisfecha, el patrón-si es
usado; de otra forma el patrón-no es usado (si está
presente). Si hay más de dos alternativas en el
sub-patrón, se produce un error en tiempo de
compilación.
Hay dos clases de condición. Si el texto entre los
paréntesis consiste de una secuencia de dÃgitos,
entonces la condición es satisfecha si el
sub-patrón de captura de ese número ha sido
coincidido previamente. Consideremos el siguiente patrón,
el cual contiene espacios en blanco sin significado para hacerlo
más legible (asumiendo la opción PCRE_EXTENDED)
y lo dividimos en tres partes para facilitar su discusión:
( \( )? [^()]+ (?(1) \) )
La primera parte coincide con un paréntesis de apertura
opcional, y si ese caracter está presente, lo define como
la primera subcadena capturada. La segunda parte coincide con uno
o más caracteres que no sean paréntesis. La tercera
parte es un sub-patrón condicional que examina si el
primer conjunto de paréntesis coincidió o no. Si lo
hizo, es decir, si el asunto comenzó con un
paréntesis de apertura, la condición es cierta,
asà que el patrón-si es ejecutado y un
paréntesis de cierre es requerido. De otro modo, ya que no
existe un patrón-no, el sub-patrón coincide con
nada. En otras palabras, este patrón coincide con una
secuencia de no-paréntesis, opcionalmente entre
paréntesis.
Si la condición es la cadena (R), es
satisfecha si se ha hecho una llamada recursiva al patrón
o sub-partón. En el "nivel superior", la condición
es falsa.
Si la condición no es una secuencia de dÃgitos o
(R), debe ser una aserción. Ésta puede ser una
aserción positiva o negativa hacia adelante o hacia
atrás. Considere este patrón, el cual contiene una
vez más espacios en blanco sin significado, y con las dos
alternativas en la siguiente lÃnea:
(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
La condición es una aserción positiva hacia
adelante que coincide con una secuencia opcional de no-letras
seguida por una letra. En otras palabras, examina la presencia de
al menos una letra en el asunto. Si se encuentra una letra, el
asunto es comparado contra la primera alternativa; de otra forma
lo es con la segunda. Este patrón coincide con cadenas en
una de las dos formas dd-aaa-dd o dd-dd-dd, en donde aaa son
letras y dd son dÃgitos.
Comentarios
La secuencia (?# marca el inicio de un comentario el cual
continúa hasta el siguiente paréntesis de
cierre. Los paréntesis anidados no son permitidos. Los
caracteres que forman un comentario no hacen parte del
patrón de coincidencia en ningún caso.
Si la opción PCRE_EXTENDED
es definida, un caracter # no escapado por fuera de una clase de
caracteres crea un comentario que continúa hasta el
próximo caracter de nueva lÃnea en el
patrón.
Patrones recursivos
Considere el problema de coincidir con una cadena entre
paréntesis, permitiendo un número ilimitado de
paréntesis anidados. Sin el uso de recursiones, lo mejor
que puede lograrse es usar un patrón que coincida hasta
un número lÃmite de profundidad en el
anidamiento. No es posible manejar una profundidad arbitraria de
anidamiento. Perl 5.6 contiene una caracterÃstica
experimental que permite que las expresiones regulares sean
recursivas (entre otras cosas). El elemento especial (?R)
está disponible para el caso especÃfico de
recursión. Este patrón de PCRE resuelve el
problema de los paréntesis (asumiendo que la
opción PCRE_EXTENDED
es definida, de modo que los espacios en blanco sean ignorados):
\( ( (?>[^()]+) | (?R) )* \)
Primero coincide con un paréntesis de apertura. Luego
coincide con cualquier número de subcadenas, que pueden
ser o bien una secuencia de no-paréntesis, o una
coincidencia recursiva del patrón mismo (es decir, una
subcadena correctamente envuelta por
paréntesis). Finalmente hay un paréntesis de
cierre.
Este patrón de ejemplo en particular contiene repeticiones
anidadas ilimitadas, asà que el uso de un
sub-patrón de una aplicación para la
comparación de cadenas de no-paréntesis es
importante cuando se aplica el patrón a cadenas que no
coinciden. Por ejemplo, cuando se aplica a
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
descubre una "no coincidencia" rápidamente. Sin embargo,
si un sub-patrón de una aplicación no es usado, la
comparación es ejecutada por un tiempo muy largo realmente
ya que hay muchas formas diferentes en las que las repeticiones +
y * pueden moldear el asunto, y todas deben ser probadas antes
que pueda reportarse el fallo.
Los valores establecidos para cualquier sub-patrón de
captura son aquellos del nivel de recursión más
externo en el que esté definido el valor del
sub-patrón. Si el patrón anterior fuera comparado
contra
(ab(cd)ef)
el valor para los paréntesis de captura es "ef", el cual
es el último valor tomado del nivel superior. Si se
agregan paréntesis adicionales, produciendo
\( ( ( (?>[^()]+) | (?R) )* ) \)
entonces la cadena que capturan es "ab(cd)ef", los contenidos de
los paréntesis del nivel superior. Si hay más de 15
paréntesis de captura en un patrón, PCRE tiene que
obtener memoria extra para almacenar datos durante una
recursión, cosa que logra usando pcre_malloc, y la libera
más adelante mediante pcre_free. Si no se puede obtener
memoria, guarda datos únicamente para los primeros 15
paréntesis de captura, dado que no hay forma de producir
un error de memoria-insuficiente desde el interior de una
recursión.
A partir de PHP 4.3.3, (?1),
(?2) y demás pueden usarse para
sub-patrones recursivos también. Asimismo es posible usar
sub-patrones con nombre:
(?P>foo).
Si la sintaxis para una referencia de sub-patrón
recursivo (ya sea por número o por nombre) es usada por
fuera de los paréntesis a los que hace referencia, opera
como una subrutina en un lenguaje de programación. Un
ejemplo anterior anotaba que el patrón
(sens|respons)e and \1ibility coincide con
"sense and sensibility" y "response and responsibility", pero no
con "sense and responsibility". Si en su lugar se usa el
patrón (sens|respons)e and
(?1)ibility, entonces efectivamente coincide con
"sense and responsibility" al igual que con las otras dos
cadenas. Sin embargo, tales referencias deben seguir al
sub-patrón al que hacer referencia.
Rendimientos
Ciertos elementos que pueden aparecer entre los patrones son
más eficientes que otros. Es más eficiente usar
una clase de caracteres como [aeiou] que un conjunto de
alternativas tal como (a|e|i|o|u). En general, la
contrucción más simple que ofrezca el
comportamiento requerido es usualmente la más
eficiente. El libro de Jeffrey Friedl contiene una cantidad
considerable de comentarios sobre la optimización de
expresiones regulares para un rendimiento eficiente.
Cuando un patrón empieza con .* y la opción PCRE_DOTALL
está definida, el patrón es anclado
implÃcitamente por PCRE, ya que sólo puede
coincidir al inicio de la cadena de asunto. Sin embargo, si PCRE_DOTALL no
es definido, PCRE no puede hacer esta optimización, ya que
el meta-caracter . no coincide entonces con una nueva
lÃnea y si la cadena de asunto contiene nuevas
lÃneas, el patrón podrÃa coincidir desde el
caracter inmediatamente siguiente a una de ellas en vez del
inicio absoluto. Por ejemplo, el patrón
(.*) second
coincide con el asunto "first\nand second" (en donde \n
representa un caracter de nueva lÃnea) con la primera
subcadena capturada que sea "and". Para conseguirlo, PCRE tiene
que reintentar la coincidencia comenzando en cada nueva
lÃnea del asunto.
Si está usando un patrón asà con cadenas de
asunto que no contienen nuevas lÃneas, el mejor
rendimiento se obtiene definiendo PCRE_DOTALL o
iniciando el patrón con ^.* para indicar un anclamiento
explÃcito. Esto le ahorra a PCRE tener que examinar toda
la cadena de entrada buscando nuevas lÃneas para empezar
de nuevo.
Tenga cuidado con los patrones que contienen repeticiones
anidadas ilimitadas. Éstos pueden tomar un tiempo de
ejecución muy largo cuando se aplican sobre una cadena que
no coincide. Considere el fragmento de patrón
(a+)*
Éste puede coincidir con "aaaa" en 33 maneras diferentes,
y este número crece muy rápidamente a medida que la
cadena se hace más larga. (La repetición * puede
coincidir 0, 1, 2, 3, o 4 veces, y por cada uno de esos casos
diferentes a 0, las repeticiones + pueden coincidir un
número diferente de veces.) Cuando el resto del
patrón es de tal forma que la coincidencia completa
está destinada a fallar, PCRE en principio intenta cada
variación posible, y esto puede tomar un tiempo
extremadamente largo.
Una optimización atrapa algunos de los casos más
simples tales como
(a+)*b
en donde un caracter literal se encuentra a
continuación. Antes de embarcarse en el procedimiento
estándar de comparación, PCRE chequea que haya una
letra "b" más adelante en la cadena de asunto, y si no lo
hay, falla la coincidencia inmediatamente. Sin embargo, cuando no
hay un literal a continuación, esta optimización no
puede ser usada. Puede apreciar la diferencia al comparar el
comportamiento de
(a+)*\d
con el patrón anterior. El primero produce un fallo casi
instantáneamente cuando se aplica a una lÃnea
completa de caracteres "a", mientras que el segundo toma un
tiempo apreciable con cadenas más largas de
aproximadamente 20 caracteres.