"line break" is ill-defined:
-- Windows uses CR+LF (\r\n)
-- Linux LF (\n)
-- OSX CR (\r)
Little-known special character:
\R in preg_* matches all three.
preg_match( '/^\R$/', "match\nany\\n\rline\r\nending\r" ); // match any line endings
El carácter de barra invertida tiene varios usos. En primer lugar, si está seguido por un carácter no alfanumérico, elimina cualquier significado especial que el carácter pueda tener. Este uso de barra invertida como carácter de escape se aplica tanto dentro como fuera de clases de caracteres.
Por ejemplo, si desea coincidir con un carácter "*", escribe "\*" en el patrón. Esto se aplica ya sea que el carácter siguiente sería interpretado de otra manera como un metacarácter, por lo que siempre es seguro preceder un no alfanumérico con "\" para especificar que representa a sí mismo. En particular, si desea coincidir con una barra invertida, escribe "\\".
Nota:
Las cadenas de PHP con comillas simples y dobles tienen un significado especial de barra invertida. Por lo tanto, si \ debe coincidir con una expresión regular \\, entonces "\\\\" o '\\\\' debe usarse en el código PHP.
Si un patrón se compila con la opción PCRE_EXTENDED, el espacio en blanco en el patrón (excepto en una clase de caracteres) y los caracteres entre un "#" fuera de una clase de caracteres y el siguiente carácter de nueva línea se ignoran. Una barra invertida de escape puede usarse para incluir un carácter de espacio en blanco o "#" como parte del patrón.
Un segundo uso de la barra invertida proporciona una manera de codificar caracteres no imprimibles en patrones de manera visible. No hay restricción sobre la aparición de caracteres no imprimibles, aparte del cero binario que termina un patrón, pero cuando un patrón se está preparando mediante edición de texto, generalmente es más fácil usar una de las siguientes secuencias de escape que el carácter binario que representan:
El efecto preciso de "\cx
" es el siguiente:
si "x
" es una letra minúscula, se convierte
a mayúscula. Luego se invierte el bit 6 del carácter (hex 40).
Así, "\cz
" se convierte en hex 1A, pero
"\c{
" se convierte en hex 3B, mientras que "\c;
"
se convierte en hex 7B.
Después de "\x
", se leen hasta dos dígitos hexadecimales (las letras pueden estar en mayúsculas o minúsculas).
En modo UTF-8, "\x{...}
" está permitido, donde el contenido de las llaves es una cadena de dígitos hexadecimales. Se interpreta como un carácter UTF-8 cuyo número de código es el número hexadecimal dado. La secuencia de escape hexadecimal original,
\xhh
, coincide con un carácter UTF-8 de dos bytes si el valor es mayor que 127.
Después de "\0
" se leen hasta dos dígitos octales adicionales.
En ambos casos, si hay menos de dos dígitos, solo se usan los que
están presentes. Así, la secuencia "\0\x\07
"
especifica dos ceros binarios seguidos de un carácter BEL. Asegúrese de
proporcionar dos dígitos después del cero inicial si el carácter
que sigue es él mismo un dígito octal.
El manejo de una barra invertida seguida de un dígito que no sea 0 es complicado. Fuera de una clase de caracteres, PCRE lo lee y cualquier dígito siguiente como un número decimal. Si el número es menor que 10, o si ha habido al menos esa cantidad de paréntesis de apertura de captura anteriores en la expresión, la secuencia completa se toma como una referencia inversa. Una descripción de cómo funciona esto se da más adelante, después de la discusión de subpatrones entre paréntesis.
Dentro de una clase de caracteres, o si el número decimal es mayor que 9 y no ha habido tantas subpatrones de captura, PCRE vuelve a leer hasta tres dígitos octales siguientes a la barra invertida, y genera un solo byte a partir de los 8 bits menos significativos del valor. Los dígitos posteriores se representan a sí mismos. Por ejemplo:
Tenga en cuenta que los valores octales de 100 o más no deben introducirse con un cero inicial, ya que nunca se leen más de tres dígitos octales.
Todas las secuencias que definen un valor de un solo byte pueden usarse tanto dentro como fuera de clases de caracteres. Además,
dentro de una clase de caracteres, la secuencia "\b
"
se interpreta como el carácter de retroceso (hex 08). Fuera de una clase de caracteres tiene un significado diferente (ver más abajo).
El tercer uso de la barra invertida es para especificar tipos de caracteres genéricos:
Cada par de secuencias de escape divide el conjunto completo de caracteres en dos conjuntos disjuntos. Cualquier carácter dado coincide con uno, y solo uno, de cada par.
Los caracteres de "espacio en blanco" son HT (9), LF (10), FF (12), CR (13), y espacio (32). Sin embargo, si se está realizando una coincidencia específica de la configuración regional, los caracteres con puntos de código en el rango 128-255 también pueden considerarse como caracteres de espacio en blanco, por ejemplo, NBSP (A0).
Un carácter de "palabra" es cualquier letra o dígito o el carácter de subrayado,
es decir, cualquier carácter que pueda ser parte de
una "palabra" de Perl. La definición de letras y dígitos está
controlada por las tablas de caracteres de PCRE, y puede variar si se está realizando una coincidencia específica de la configuración regional. Por ejemplo, en la configuración regional "fr" (francés), algunos códigos de caracteres mayores que 128 se usan para letras acentuadas,
y estas coinciden con \w
.
Estas secuencias de tipos de caracteres pueden aparecer tanto dentro como fuera de clases de caracteres. Cada una coincide con un carácter de tipo apropiado. Si el punto de coincidencia actual está al final de la cadena de sujeto, todas fallan, ya que no hay carácter para coincidir.
El cuarto uso de la barra invertida es para ciertas afirmaciones simples. Una afirmación especifica una condición que debe cumplirse en un punto particular en una coincidencia, sin consumir ningún carácter de la cadena de sujeto. El uso de subpatrones para afirmaciones más complicadas se describe a continuación. Las afirmaciones con barra invertida son
Estas afirmaciones no pueden aparecer en clases de caracteres (pero
note que "\b
" tiene un significado diferente, a saber, el carácter de retroceso, dentro de una clase de caracteres).
Un límite de palabra es una posición en la cadena de sujeto donde
el carácter actual y el carácter anterior no coinciden ambos
con \w
o \W
(es decir, uno coincide
con \w
y el otro coincide
con \W
), o el inicio o final de la cadena si el primer
o último carácter coincide con \w
, respectivamente.
Las afirmaciones \A
, \Z
y
\z
difieren de las afirmaciones tradicionales
de circunflejo y dólar (descritas en anclajes )
en que solo coinciden en el inicio y final exactos de la cadena de sujeto,
independientemente de las opciones establecidas. No se ven afectadas por las
opciones PCRE_MULTILINE o
PCRE_DOLLAR_ENDONLY.
La diferencia entre \Z
y
\z
es que \Z
coincide antes de un salto de línea que es el último carácter de la cadena así como al final de
la cadena, mientras que \z
solo coincide al final.
La afirmación \G
es verdadera solo cuando la posición de coincidencia actual está en el punto de inicio de la coincidencia, como se especifica por
el argumento offset
de
preg_match(). Difiere de \A
cuando el valor de offset
no es cero.
\Q
y \E
pueden usarse para ignorar
metacaracteres de regexp en el patrón. Por ejemplo:
\w+\Q.$.\E$
coincidirá con uno o más caracteres de palabra,
seguido de literales .$.
y anclado al final
de la cadena. Tenga en cuenta que esto no cambia el comportamiento de
los delimitadores; por ejemplo, el patrón #\Q#\E#$
no es válido, porque el segundo #
marca el final del patrón, y el \E#
se interpreta como modificadores inválidos.
\K
puede usarse para restablecer el inicio de la coincidencia.
Por ejemplo, el patrón foo\Kbar
coincide
con "foobar", pero informa que ha coincidido con "bar". El uso de
\K
no interfiere con la configuración de subcadenas capturadas. Por ejemplo, cuando el patrón (foo)\Kbar
coincide con "foobar", la primera subcadena sigue configurada en "foo".
"line break" is ill-defined:
-- Windows uses CR+LF (\r\n)
-- Linux LF (\n)
-- OSX CR (\r)
Little-known special character:
\R in preg_* matches all three.
preg_match( '/^\R$/', "match\nany\\n\rline\r\nending\r" ); // match any line endings
Significantly updated version (with new $pat4 utilising \R properly, its results and comments):
Note that there are (sometimes difficult to grasp at first glance) nuances of meaning and application of escape sequences like \r, \R and \v - none of them is perfect in all situations, but they are quite useful nevertheless. Some official PCRE control options and their changes come in handy too - unfortunately neither (*ANYCRLF), (*ANY) nor (*CRLF) is documented here on php.net at the moment (although they seem to be available for over 10 years and 5 months now), but they are described on Wikipedia ("Newline/linebreak options" at https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions) and official PCRE library site ("Newline convention" at http://www.pcre.org/original/doc/html/pcresyntax.html#SEC17) pretty well. The functionality of \R appears somehow disappointing (with default configuration of compile time option) according to php.net as well as official description ("Newline sequences" at https://www.pcre.org/original/doc/html/pcrepattern.html#newlineseq) when used improperly.
A hint for those of you who are trying to fight off (or work around at least) the problem of matching a pattern correctly at the end ($) of any line in multiple lines mode (/m).
<?php
// Various OS-es have various end line (a.k.a line break) chars:
// - Windows uses CR+LF (\r\n);
// - Linux LF (\n);
// - OSX CR (\r).
// And that's why single dollar meta assertion ($) sometimes fails with multiline modifier (/m) mode - possible bug in PHP 5.3.8 or just a "feature"(?).
$str="ABC ABC\n\n123 123\r\ndef def\rnop nop\r\n890 890\nQRS QRS\r\r~-_ ~-_";
// C 3 p 0 _
$pat1='/\w$/mi'; // This works excellent in JavaScript (Firefox 7.0.1+)
$pat2='/\w\r?$/mi'; // Slightly better
$pat3='/\w\R?$/mi'; // Somehow disappointing according to php.net and pcre.org when used improperly
$pat4='/\w(?=\R)/i'; // Much better with allowed lookahead assertion (just to detect without capture) without multiline (/m) mode; note that with alternative for end of string ((?=\R|$)) it would grab all 7 elements as expected
$pat5='/\w\v?$/mi';
$pat6='/(*ANYCRLF)\w$/mi'; // Excellent but undocumented on php.net at the moment (described on pcre.org and en.wikipedia.org)
$n=preg_match_all($pat1, $str, $m1);
$o=preg_match_all($pat2, $str, $m2);
$p=preg_match_all($pat3, $str, $m3);
$r=preg_match_all($pat4, $str, $m4);
$s=preg_match_all($pat5, $str, $m5);
$t=preg_match_all($pat6, $str, $m6);
echo $str."\n1 !!! $pat1 ($n): ".print_r($m1[0], true)
."\n2 !!! $pat2 ($o): ".print_r($m2[0], true)
."\n3 !!! $pat3 ($p): ".print_r($m3[0], true)
."\n4 !!! $pat4 ($r): ".print_r($m4[0], true)
."\n5 !!! $pat5 ($s): ".print_r($m5[0], true)
."\n6 !!! $pat6 ($t): ".print_r($m6[0], true);
// Note the difference among the three very helpful escape sequences in $pat2 (\r), $pat3 and $pat4 (\R), $pat5 (\v) and altered newline option in $pat6 ((*ANYCRLF)) - for some applications at least.
/* The code above results in the following output:
ABC ABC
123 123
def def
nop nop
890 890
QRS QRS
~-_ ~-_
1 !!! /\w$/mi (3): Array
(
[0] => C
[1] => 0
[2] => _
)
2 !!! /\w\r?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
3 !!! /\w\R?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
4 !!! /\w(?=\R)/i (6): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
)
5 !!! /\w\v?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
6 !!! /(*ANYCRLF)\w$/mi (7): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
[6] => _
)
*/
?>
Unfortunately, I haven't got any access to a server with the latest PHP version - my local PHP is 5.3.8 and my public host's PHP is version 5.2.17.
A non breaking space is not considered as a space and cannot be caught by \s.
it can be found with :
- [\xc2\xa0] in utf-8
- \x{00a0} in unicode
As \v matches both single char line ends (CR, LF) and double char (CR+LF, LF+CR), it is not a fixed length atom (eg. is not allowed in lookbehind assertions).
Note that there are (sometimes difficult to grasp at first glance) nuances of meaning and application of escape sequences like \r, \R and \v - none of them is perfect in all situations, but they are quite useful nevertheless. Some official PCRE control options and their changes come in handy too - unfortunately neither (*ANYCRLF), (*ANY) nor (*CRLF) is documented here on php.net at the moment (although they seem to be available for over 10 years and 5 months now), but they are described on Wikipedia ("Newline/linebreak options" at https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions) and official PCRE library site ("Newline convention" at http://www.pcre.org/original/doc/html/pcresyntax.html#SEC17) pretty well. The functionality of \R appears somehow disappointing (with default configuration of compile time option) according to php.net as well as official description ("Newline sequences" at https://www.pcre.org/original/doc/html/pcrepattern.html#newlineseq).
A hint for those of you who are trying to fight off (or work around at least) the problem of matching a pattern correctly at the end ($) of any line in multiple lines mode (/m).
<?php
// Various OS-es have various end line (a.k.a line break) chars:
// - Windows uses CR+LF (\r\n);
// - Linux LF (\n);
// - OSX CR (\r).
// And that's why single dollar meta assertion ($) sometimes fails with multiline modifier (/m) mode - possible bug in PHP 5.3.8 or just a "feature"(?).
$str="ABC ABC\n\n123 123\r\ndef def\rnop nop\r\n890 890\nQRS QRS\r\r~-_ ~-_";
// C 3 p 0 _
$pat1='/\w$/mi'; // This works excellent in JavaScript (Firefox 7.0.1+)
$pat2='/\w\r?$/mi';
$pat3='/\w\R?$/mi'; // Somehow disappointing according to php.net and pcre.org
$pat4='/\w\v?$/mi';
$pat5='/(*ANYCRLF)\w$/mi'; // Excellent but undocumented on php.net at the moment
$n=preg_match_all($pat1, $str, $m1);
$o=preg_match_all($pat2, $str, $m2);
$p=preg_match_all($pat3, $str, $m3);
$r=preg_match_all($pat4, $str, $m4);
$s=preg_match_all($pat5, $str, $m5);
echo $str."\n1 !!! $pat1 ($n): ".print_r($m1[0], true)
."\n2 !!! $pat2 ($o): ".print_r($m2[0], true)
."\n3 !!! $pat3 ($p): ".print_r($m3[0], true)
."\n4 !!! $pat4 ($r): ".print_r($m4[0], true)
."\n5 !!! $pat5 ($s): ".print_r($m5[0], true);
// Note the difference among the three very helpful escape sequences in $pat2 (\r), $pat3 (\R), $pat4 (\v) and altered newline option in $pat5 ((*ANYCRLF)) - for some applications at least.
/* The code above results in the following output:
ABC ABC
123 123
def def
nop nop
890 890
QRS QRS
~-_ ~-_
1 !!! /\w$/mi (3): Array
(
[0] => C
[1] => 0
[2] => _
)
2 !!! /\w\r?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
3 !!! /\w\R?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
4 !!! /\w\v?$/mi (5): Array
(
[0] => C
[1] => 3
[2] => p
[3] => 0
[4] => _
)
5 !!! /(*ANYCRLF)\w$/mi (7): Array
(
[0] => C
[1] => 3
[2] => f
[3] => p
[4] => 0
[5] => S
[6] => _
)
*/
?>
Unfortunately, I haven't got any access to a server with the latest PHP version - my local PHP is 5.3.8 and my public host's PHP is version 5.2.17.