2012-06-15 30 views
20

Sólo por curiosidad, estoy tratando de averiguar cuál es exactamente la manera correcta para escapar de una barra invertida para su uso en un patrón de expresión regular PHP, así:Forma correcta de escapar de la barra invertida [] en PHP regex?

PRUEBA 01: (3 barras invertidas)

$pattern = "/^[\\\]{1,}$/"; 
$string = '\\'; 

// ----- RETURNS A MATCH ----- 

TEST 02: (4 barras invertidas)

$pattern = "/^[\\\\]{1,}$/"; 
$string = '\\'; 

// ----- ALSO RETURNS A MATCH ----- 

de acuerdo con los artículos por debajo, 4 es supuestamente la manera correcta pero w Lo que me confunde es que ambas pruebas dieron una coincidencia. Si ambos tienen razón, entonces ¿4 es la forma preferida?

RECURSOS:

Respuesta

4

Lo que pasa es que estás usando una clase de caracteres, [], por lo que no importa cuántas barras invertidas son literales incrustado en él, se tratará como una sola barra invertida.

p. Ej. las siguientes dos expresiones regulares:

/[a]/ 
/[aa]/ 

son para todos los efectos idénticos en la medida que el motor de expresiones regulares se refiere. Las clases de caracteres toman una lista de caracteres y la "colapsan" para que coincida con un solo carácter, en la línea de "para el personaje actual que se está considerando, ¿es alguno de los caracteres enumerados dentro del []?". Si enumera dos barras diagonales inversas en la clase, entonces será "¿el carbon es una barra negra o es una barra diagonal inversa?".

+0

Entonces, ¿en ambos casos, el motor de expresiones regulares lo considera una sola barra invertida? –

+3

'\ [\]' sería un escape del corchete de cierre. '[\\]' sería una barra invertida en una clase de caracteres. una sola clase de char es bastante inútil, no sería diferente de tener un simple '\\\'. –

35
// PHP 5.4.1 

// Either three or four \ can be used to match a '\'. 
echo preg_match('/\\\/', '\\');  // 1 
echo preg_match('/\\\\/', '\\');  // 1 

// Match two backslashes `\\`. 
echo preg_match('/\\\\\\/', '\\\\'); // Warning: No ending delimiter '/' found 
echo preg_match('/\\\\\\\/', '\\\\'); // 1 
echo preg_match('/\\\\\\\\/', '\\\\'); // 1 

// Match one backslash using a character class. 
echo preg_match('/[\\]/', '\\');  // 0 
echo preg_match('/[\\\]/', '\\');  // 1 
echo preg_match('/[\\\\]/', '\\');  // 1 

Al utilizar tres barras invertidas para que coincida con un '\' el patrón de abajo se interpreta como que coincida con un '\' seguido de un 's'.

echo preg_match('/\\\\s/', '\\ '); // 0 
echo preg_match('/\\\\s/', '\\s'); // 1 

Al usar cuatro barras invertidas para que coincida con un '\' el patrón de abajo se interpreta como que coincida con un '\' seguido por un carácter de espacio.

echo preg_match('/\\\\\s/', '\\ '); // 1 
echo preg_match('/\\\\\s/', '\\s'); // 0 

Lo mismo se aplica si dentro de una clase de caracteres.

echo preg_match('/[\\\\s]/', ' '); // 0 
echo preg_match('/[\\\\\s]/', ' '); // 1 

Ninguno de los anteriores resultados se ven afectados por encerrar las cadenas en doble en vez de comillas simples.

Conclusiones:
Ya sea dentro o fuera de una clase de caracteres entre corchetes, una barra invertida literal se pueden combinar usando sólo tres barras invertidas '\\\' a menos que el siguiente carácter en el patrón también se barra invertida, en cuyo caso la barra invertida debe ser emparejado usando cuatro barras invertidas.

Recomendación:
Siempre usa cuatro barras invertidas '\\\\' en un patrón de expresión en la búsqueda para que coincida con una barra invertida.

Escape sequences.

+0

Cuando pruebo [\\], siempre obtengo el mensaje: preg_match(): Compilación fallida: falta la terminación] para la clase de caracteres en el desplazamiento 3 – CMCDragonkai

+0

Debe marcarse como la respuesta @Mahmoud Tahan – Lsakurifaisu

0

Lo he estudiado hace años. Esto se debe a que la 1ra barra invertida se escapa del 2do y juntos forman un caracter de 'verdadero baclkslash' en el patrón y este verdadero escapa del tercero. Por lo tanto, mágicamente hace que funcionen 3 barras invertidas.

Sin embargo, la sugerencia normal es utilizar 4 barras diagonales inversas en lugar de las 3 barras diagonales inversas ambiguas.

Si me equivoco acerca de algo, no dude en corregirme.

+1

-1: 'y este verdadero escapa el 3 ° 'No. Solo se realiza un pase. La tercera barra invertida "escapa" de ']' (que simplemente da como resultado ']'). –

+0

@ Luminosidad: ¿Entonces por qué '/ (\\\ r) \ 1 + /' coincidirá repetidamente con '\' y 'r' (quiero decir 2 caracteres verdaderos)? ¿Puedes explicar? –

+0

'\ r' es una secuencia de escape; '\]' no es. –

9

para evitar este tipo de código claro puede utilizar \ X5c gusta esta :)

echo preg_replace('/\x5c\w+\.php$/i', '<b>${0}</b>', __FILE__); 
+0

Solo quiero agradecerle enormemente por esto. Escapar de personajes de escape como '\ n' ya es doloroso, pero hacerlo en expresiones regulares con lookbehind es un desafío. –

0

También puede utilizar los siguientes

$regexp = <<<EOR 
schemaLocation\s*=\s*["'](.*?)["'] 
EOR; 
preg_match_all("/".$regexp."/", $xml, $matches); 
print_r($matches); 

palabras clave: dochere, nowdoc

Cuestiones relacionadas