|
La biblioteca PCRE es un conjunto de funciones que implementa comparaciones con patrones de expresiones regulares usando usando la misma sintaxis y semántica de Perl 5, con tan solo unas pocas diferencias (ver más adelante). La implementación actual corresponde a Perl 5.005.
Las diferencias descritas aquí existen con respecto a Perl 5.005.
Por defecto, un caracter de espacio en blanco es cualquier caracter que reconozca la función isspace() de la biblioteca C, aunque es posible compilar PCRE con tablas alternativas de tipos de caracteres. Normalmente, isspace() coincide con el espacio, la alimentación de página, la nueva línea, el retorno de carro, el tabulador horizontal y el tabulador vertical. Perl 5 ya no incluye el tabulador vertical en su conjunto de caracteres de espacio en blanco. La secuencia de escape \v que permaneció durante mucho tiempo en la documentación de Perl nunca fue reconocida en realidad. Sin embargo, el caracter mismo era tratado como espacio en blanco por lo menos hasta 5.002. En 5.004 y 5.005 no coincide con \s.
PCRE no permite cuantificadores de repetición en aserciones hacia adelante. Perl las permite, pero no quieren decir lo que probablemente piense. Por ejemplo, (?!a){3} no quiere decir que los siguientes tres caracteres no sean "a". Simplemente indica que el siguiente caracter no sea "a" tres veces.
Los sub-patrones de captura que aparecen al interior de aserciones negativas hacia adelante son contados, pero sus entradas en el vector de desplazamientos no son definidas. Perl define sus variables numéricas a partir de cualquiera de tales patrones que coinciden antes que la aserción falle en coincidir algo (y por lo tanto tiene éxito), pero solo si la aserción negativa hacia adelante contiene una sola rama.
Aunque los caracteres de cero binario son soportados en la cadena de asunto, no son permitidos en una cadena de patrón porque éstas son pasadas como un cadena normal de C, terminada en cero. La secuencia de escape "\0" puede ser usada en el patrón para representar el cero binario.
Las siguientes secuencias de escape de Perl no son soportadas: \l, \u, \L, \U. De hecho, estas son implementadas por el mecanismo de gestión general de cadenas de Perl y no son parte de su motor de comparación de patrones.
La aserción \G de Perl no es soportada, ya que no es relevante para las coincidencias sencillas de patrones.
Obviamente, PCRE no soporta la construcción (?{código}).
En la actualidad hay algunas peculiaridades en Perl 5.005_02 con respecto a los grupos de cadenas capturadas cuando parte de un patrón se repite. Por ejemplo, al coincidir "aba" con el patrón /^(a(b)?)+$/ se define $2 como "b", pero al coincidir "aabbaa" con /^(aa(bb)?)+$/ deja $2 sin definir. Sin embargo, si el patrón se modifica a /^(aa(b(b))?)+$/ entonces $2 (y $3) se definen. En Perl 5.004 se define $2 en ambos casos, y también ocurre en PCRE. Si en el futuro Perl se adapta a un estilo consistente que sea diferente, PCRE puede cambiar para ajustarse.
Otra discrepancia aún no resuelta consiste en que, en Perl 5.005_02, el patrón /^(a)?(?(1)a|b)+$/ coincide con la cadena "a", pero en PCRE no. Sin embargo, tanto en Perl como en PCRE /^(a)?a/ coincide con "a", dejando $1 sin definir.
PCRE ofrece algunas extensiones a las capacidades de expresiones regulares de Perl:
Aunque las aserciones hacia atrás deben coincidir con cadenas de longitud fija, cada rama alternativa de una aserción hacia atrás puede coincidir con una longitud diferente de cadena. Perl 5.005 requiere que todas ellas tengan la misma longitud.
Si PCRE_DOLLAR_ENDONLY se define y PCRE_MULTILINE no, el meta-caracter $ sólo coincide al final absoluto de la cadena.
Si se define PCRE_EXTRA, una barra invertida seguida de una letra sin significado especial provoca un error.
Si se define PCRE_UNGREEDY, la ambición de los cuantificadores de repetición es invertida, es decir, no son ambiciosos por defecto, pero si son seguidos de un signo de interrogación, sí lo será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.
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
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
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:
alarma, esto es, el caracter BEL (hexadecimal 07)
"control-x", en donde x es cualquier caracter
escape (hexadecimal 1B)
alimentación de página (hexadecimal 0C)
nueva línea (hexadecimal 0A)
retorno de carro (hexadecimal 0D)
tabulador (hexadecimal 09)
caracter con código hexadecimal hh
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:
es otro modo de escribir un espacio
es lo mismo, siempre que haya menos de cuarenta sub-patrones de captura previos
siempre es una referencia hacia atrás
puede ser una referencia hacia atrás, u otra forma de escribir un tabulador
siempre es un tabulador
es un tabulador seguido del caracter "3"
es el caracter con el código octal 113 (ya que no puede haber más de 99 referencias hacia atrás)
es un byte que consiste completamente de bits 1
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:
cualquier dígito decimal
cualquier caracter que no sea un dígito decimal
cualquier caracter de espacio en blanco
cualquier caracter que no sea un espacio en blanco
cualquier caracter de "palabra"
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
límite de palabra
no-límite de palabra
inicio de la cadena de asunto (independiente del modo multilínea)
fin de la cadena de asunto o una nueva línea al final (independiente del modo multilínea)
fin de la cadena de asunto (independiente del modo multilínea)
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.
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:
un caracter con la propiedad xx
un caracter sin la propiedad xx
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.
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.
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.
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..
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.
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
i | para PCRE_CASELESS |
m | para PCRE_MULTILINE |
s | para PCRE_DOTALL |
x | para PCRE_EXTENDED |
U | para PCRE_UNGREEDY |
X | para PCRE_EXTRA |
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.
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.
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".
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.
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.
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.
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.
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.
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.
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.
Hosting by: hurra.com
Generated: 2007-01-26 18:00:53