2011-03-18 18 views
16

Me encuentro con un problema cuando se trata de emparejar subpatrones que involucran el signo de dólar. Por ejemplo, considere el siguiente fragmento de texto:

Regular Price: $20.50  Final Price: $15.20 
Regular Price: $18.99  Final Price: $2.25 
Regular Price: $11.22  Final Price: $33.44 
Regular Price: $55.66  Final Price: $77.88 

yo estaba tratando de igualar los conjuntos precio final/regulares con la siguiente expresión regular, pero simplemente no estaba trabajando (no hay coincidencias en todos):
preg_match_all("/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U", $data, $matches);

Me escapé del signo de dólar, así que ¿qué da?

+1

Intenta escapar con \\\ en los signos de dólar. Podría estar bien inferir una relación entre el signo de dólar problemático y el hecho de que PHP usa $ para hacer algo de trabajo. (Yo uso $ para hacer el trabajo también, solo parece lógico). –

+3

¿Has probado las comillas simples sin escapar de $? – palindrom

Respuesta

32

Dentro de una cadena con comillas dobles, la barra diagonal inversa se trata como un carácter de escape para el $. La barra invertida es eliminado por el intérprete PHP, incluso antes de la función preg_match_all ve:

$r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U"; 
var_dump($r); 

salida (ideone):

 
"/Regular Price: $(\d+\.\d{2}).*Final Price: $(\d+\.\d{2})/U" 
       ^      ^
       the backslashes are no longer there 

Para solucionar este uso de una sola cadena entre comillas en lugar de una cadena entre comillas dobles:

preg_match_all('/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U', 
       $data, 
       $matches); 

ver su funcionamiento en línea: ideone

+0

... o también puede agregar un \ antes del '\ $' con el mismo resultado. Es menos bonito, pero funciona igual de bien. –

+0

Tuve el mismo problema, sintiéndome bastante estúpido en este momento, ¡gracias! – jreed121

+0

Su solución también funcionó para mí usando perl – Filype

6

Sé que esta pregunta es un poco antigua, pero encontré esto al intentar encontrar la respuesta al mismo problema. Vi que estaba en la parte superior de los motores de búsqueda, por lo que pensé que sería bueno para explicar una alternativa sencilla, y por qué esto sucede con las cadenas dobles citados (")

La expresión regular que estaba usando contenida mucha sola cite los caracteres (') en él, así que no estaba demasiado interesado en envolver la expresión con ellos, ya que no quería escapar de todos esos.

Mi solución fue "escapar por partida doble" del signo de dólar. En su ejemplo, debe ser algo similar a

"/Regular Price: \\\$(\d+\.\d{2}).*Final Price: \\\$(\d+\.\d{2})/U"; 

Tenga en cuenta que el signo del dólar contiene 3 barras ahora \\\.

Básicamente, tenemos dos "niveles" de interpretación, el de PHP y el de la expresión de expresiones regulares. Lo que sucede es que con una barra oblicua, PHP lo interpreta como un carácter literal en lugar de un modificador de variable, por lo que come la barra, interpreta la cadena como se indica en la respuesta de Mark y luego la envía a regex, que interpreta como un look-behind.

Por "doble escape" del signo de dólar, PHP interpreta \\\$ como \\ y \$ respectivamente. Nos escapamos del \ del primer conjunto de caracteres, y escapamos del $ del segundo conjunto, lo que da como resultado \$ después de la interpretación de PHP. Esto enviará la cadena literal

"/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U"; 

de expresiones regulares, que interpretará \$ como el carácter literal $, que coincidirá con $ en lugar de actuar como una mirada atrás, ya que se escapó.Es importante darse cuenta de las capas dobles de interpretación aquí, ya que tanto PHP como expresiones regulares tienen sus propias reglas de interpretación, y puede tomar hasta 4 barras para escapar correctamente de los caracteres.

cadenas comilla simple no tienen este problema, ya que al utilizar una variable $foo en una cadena, tendríamos que escribir

'Hello '. $foo .'!'; 

en lugar de

"Hello $foo!"; 

Al igual que podamos en doble instrumentos de cuerda. A diferencia de las cadenas de comillas dobles, las cadenas de comillas simples no pueden interpretar las variables dentro de la cadena como variables (a menos que se anexen como en el ejemplo anterior), en lugar de interpretarlas como texto sin formato. Ya que no tenemos que escapar de la variable más, podemos llegar lejos con sólo

'/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U' 

que enviará a \$ expresiones regulares, lo mismo que con \\\$ en una cadena de comillas dobles.

Todo es una cuestión de preferencia personal sobre qué estilo utiliza o cuál es más fácil para el patrón.

TL; DR: Uso \$ para las cadenas entre comillas simples como '/Hello \$bob/is', y \\\$ para cuerdas dobles citados como "/Hello \\\$bob/is".

Cuestiones relacionadas