2010-01-27 4 views
7

Al probar una respuesta para another user's question encontré algo que no entiendo. El problema era reemplazar todos los caracteres literales \t\n\r de una cadena con un espacio simple.Se necesita una barra invertida adicional en el patrón de expresiones regulares PHP

Ahora, el primer patrón que probé fue:

/(?:\\[trn])+/ 

que, sorprendentemente, no funcionó. Probé el mismo patrón en Perl y funcionó bien. Después de algún ensayo y error descubrí que quiere PHP 3 o 4 barras invertidas para ese patrón a la altura, como en:

/(?:\\\\[trn])+/ 

o

/(?:\\\[trn])+/ 

estos patrones - a mi sorpresa - tanto trabajo. ¿Por qué son estas barras invertidas adicionales necesarias?

+1

se integran en el lenguaje, por lo que necesita sólo dos barras invertidas. –

Respuesta

12

Necesitas 4 barras invertidas para representar 1 en expresiones regulares porque:

  • 2 barras invertidas se utilizan para unescape en una cadena ("\\\\" -> \\)
  • 1 barra invertida se utiliza para unescape en el motor de expresiones regulares (\\ -> \)

Desde el doc PHP,

escapar cualquier otro personaje dará lugar a la barra invertida se está imprimiendo demasiado 1

Por tanto, para \\\[,

  • 1 barra invertida se utiliza para la representación no literal de la \, una estancia porque \[ no es válido ("\\\[" -> \\[)
  • 1 barra diagonal inversa se utiliza para unescaping en el motor de expresiones regulares (\\[ -> \[)

Sí, funciona, pero no es una buena práctica.

2

La expresión regular es solo /(?:\\[trn])+/. Pero ya que se necesita para escapar de las barras invertidas en las declaraciones de cuerda, así, cada barra invertida debe expresarse con \\:

"/(?:\\\\[trn])+/" 
'/(?:\\\\[trn])+/' 

sólo tres teclas de retroceso hará también funcionan porque PHP no conoce la secuencia de escape \[ y lo ignora. Por lo tanto, \\ se convertirá en \, pero \[ se quedará en \[.

+0

Entonces, ¿por qué funcionan 3 barras invertidas? ¿Y por qué las comillas simples no son diferentes de las comillas dobles en este caso? –

+0

@kemp: Actualizado mi respuesta. – Gumbo

+0

Gumbo :: solo para saber si entendí correctamente - este caso funciona porque '\ [' no es un carácter de control ** y ** no se convierte en un corchete cuadrado literal porque el patrón se analiza de izquierda a derecha entonces la barra diagonal inversa se une a la anterior y anteriormente se escapó? –

8

Sus obras en Perl Dado que se transfieren que directamente como patrón de expresión /(?:\\[trn])+/

pero en php, tiene que pasar por la cadena, por lo que necesitan extra de escape de barra invertida en sí.

"/(?:\\\\[trn])+/" 

la expresión regular \ para que coincida con una sola barra invertida se convertiría en '/ \\\\ /' como PHP preg string

-2

Uso str_replace!

$code = str_replace(array("\t","\n","\r"),'',$code); 

debe hacer el truco

expresiones regulares de Perl
+1

Esto no responde a mi pregunta, y también es incorrecto porque str_replace() no permite la sustitución de todos los caracteres solicitados (independientemente de cuántos sean) con una comilla simple; puede eliminarlos todos. –

+0

@kemp sí lo hace. Si no se elimina tal como está, pruebe las combinaciones de \ r \ n o \ n \ r – AntonioCS

+1

No, no puede sustituir, por ejemplo, tres (o cualquier número arbitrario) de aquellos con un solo espacio en blanco, a menos que desee proporcionar ** cada ** combinación posible. Lo que hace tu código es simplemente eliminarlos a todos. –

Cuestiones relacionadas