2011-03-30 16 views
22

acabo de escribieron una expresión regular para su uso con la función php preg_match que contiene la siguiente parte:¿Qué caracteres literales deberían escaparse en una expresión regular?

[\w-.] 

para que coincida con cualquier carácter de palabra, así como un signo menos y el punto. Si bien parece funcionar en preg_match, traté de ponerlo en una utilidad llamada Reggy y se queja sobre "Rango vacío en la clase de caracteres". Ensayo y error me enseñaron que este problema fue resuelto por escapar del signo menos, convirtiendo la expresión regular en

[\w\-.] 

Puesto que el original parece funcionar en PHP, me pregunto por qué debería o no debería estar escapando el signo menos y, dado que el punto también es un personaje con un significado en PHP, por qué no necesitaría escapar del punto. ¿La utilidad que uso es simplemente tonta, está funcionando con otro dialecto de expresiones regulares o es incorrecto mi expresión regular y tengo suerte de que preg_match me permita salir con la suya?

+0

¿Hay alguna razón para no usar 'preg_quote'? – Okonomiyaki3000

+0

Probablemente no. Pero esa no es la razón por la que hice la pregunta. Estaba tratando de aprender algo nuevo sobre expresiones regulares, simplemente usar 'preg_quote' tendría exactamente el efecto opuesto. :). Me doy cuenta de que etiqueté este PHP, pero estaba buscando una respuesta que pueda aplicarse a cualquier implementación de PCRE. –

+0

Ya veo. Entonces, puedo sugerir: https://github.com/php/php-src/blob/a3ca6b09cdf1ed904d3e3a56878c1cf6b1a04d1b/ext/pcre/php_pcre.c – Okonomiyaki3000

Respuesta

54

En muchas implementaciones de expresiones regulares, se aplican las siguientes reglas:

caracteres Meta dentro de una clase de caracteres son:

  • ^ (negación)
  • - (rango)
  • ] (fin de la clase)
  • \ (escape char)

Por lo tanto, todos deben escaparse. Hay algunos casos de esquina sin embargo:

  • - necesidades de escapar si se coloca en el comienzo mismo, o al final de la clase (o [abc-][-abc]). En bastantes implementaciones de expresiones regulares, también no necesita escaparse cuando se coloca directamente después de un rango ([a-c-abc]) o una clase de caracteres abreviados ([\w-abc]). Esto es lo que observó
  • ^ necesidades de escapar cuando es no al inicio de la clase: [^a] significa cualquier carbón, excepto a y [a^] partidos ya sea a o ^, lo que equivale a: [\^a]
  • ] necesidades de escapar si es el único personaje de la clase: []] coincide con el carbón ]
+0

Excelente respuesta. –

+0

Respuesta muy completa, gracias. Una pregunta sobre '[]]': si solo tiene un carácter en la clase, ¿por qué no especificarlo como '\]'? (es decir, no entre corchetes) –

+0

@Pelle "por qué no" es otra pregunta, irrelevante. "Hay más de una forma de hacerlo" es un lema del inventor de preg;) –

4

Si bien hay some characters should be escaped in a regex, no se pregunta sobre la expresión regular sino sobre la clase de caracteres. Donde el símbolo del tablero es especial.

en lugar de escapar de ella se podía ponerlo al final de la clase, [\w.-]

6
[\w.-] 
  • la . por lo general significa cualquier carácter, sino entre [] tiene ningún significado especial
  • - entre [] indica un rango a menos que sea escapado o sea el primero o el último carácter entre []
+0

¿El '.' significa realmente 'cualquier carácter' mientras está en una clase de personaje? (es decir, entre corchetes) –

+0

@Pelle eso es verdad. Solo estoy editando la respuesta. la mayoría de las respuestas se equivocaron ;-) –

3

El punto final pierde su significado meta en la clase de caracteres.

El - tiene un significado especial en la clase de caracteres. Si no se coloca al inicio o al final de los corchetes, se debe escapar. De lo contrario, denota un rango de caracteres (A-Z).

Disparó otra caja especial sin embargo. [\w-.] funciona porque \w no denota un solo carácter. Como tal, PCRE no puede crear un rango de caracteres. \w es una clase de símbolos posiblemente no coherente, por lo que no hay un carácter final que podría usarse para crear el rango Z till .. También el punto de partida . precedería al primer carácter ascii a que \w podría coincidir. No hay rango construible. Por lo tanto, por qué - funcionó sin escaparse por ti.

0

Si está usando PHP y tiene que escapar caracteres especiales de expresiones regulares, simplemente utilizar preg_quote:

Un ejemplo de php.net:

<?php 
// In this example, preg_quote($word) is used to keep the 
// asterisks from having special meaning to the regular 
// expression. 

$textbody = "This book is *very* difficult to find."; 
$word = "*very*"; 
$textbody = preg_replace ("/" . preg_quote($word, '/') . "/", 
          "<i>" . $word . "</i>", 
          $textbody); 
?> 
Cuestiones relacionadas