php - signo - simbolo del dolar
Regex falla cuando el patrón involucra un signo de dólar($) (2)
Tengo un pequeño problema cuando se trata de hacer coincidir los subpatrones que involucran el signo del dólar. Por ejemplo, considere la siguiente porción 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
Estaba intentando hacer coincidir los conjuntos de precios Regular / Final con la siguiente expresión regular, pero simplemente no funcionaba (no hay coincidencias):
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?
Dentro de una cadena de doble comillas, la barra diagonal inversa se trata como un carácter de escape para el $
. El parser de PHP elimina la barra invertida incluso antes de que la función preg_match_all
vea:
$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 problema, utilice una cadena entre comillas simples en lugar de una cadena entre comillas dobles:
preg_match_all(''/Regular Price: /$(/d+/./d{2}).*Final Price: /$(/d+/./d{2})/U'',
$data,
$matches);
Sé que esta pregunta es un poco antigua, pero la encontré al intentar encontrar la respuesta al mismo problema. Vi que estaba en la parte superior de los rankings de los motores de búsqueda, por lo que pensé que sería bueno explicar una alternativa simple, y por qué esto sucede con cadenas de doble comillas ( " )
La expresión regular que estaba usando contenía un montón de caracteres de comillas simples ( '' )
, así que no me gustaba mucho envolver la expresión con ellos, ya que no quería escapar de todos ellos.
Mi solución fue "doble escape" del signo de dólar. En tu ejemplo, debería verse algo similar a
"/Regular Price: ///$(/d+/./d{2}).*Final Price: ///$(/d+/./d{2})/U";
Tenga en cuenta que el signo de dólar contiene 3 barras ahora ///
.
Básicamente, tenemos dos "niveles" de interpretación, el de PHP y el de la expresión regular. Lo que está sucediendo es que con una barra, PHP lo interpreta como un carácter literal en lugar de un modificador de variable, por lo que se come la barra, interpreta la cadena como se describe en la respuesta de Mark y luego la envía a expresiones regulares, que se interpreta como una mirada atrás.
Al "doble escape" del signo de dólar, PHP interpreta ///$
como //
y /$
respectivamente. Escapamos el /
del primer conjunto de caracteres, y escapamos el $
del segundo conjunto, dando como resultado solo /$
después de la interpretación de PHP. Esto enviará la cadena literal
"/Regular Price: /$(/d+/./d{2}).*Final Price: /$(/d+/./d{2})/U";
a regex, que interpretará /$
como el carácter literal $
, que coincidirá con $
lugar de actuar como una mirada hacia atrás, ya que se escapó. Es importante darse cuenta de las dobles capas de interpretación aquí, ya que tanto PHP como las expresiones regulares tienen sus propias reglas de interpretación, y puede tomar hasta 4 barras para escapar de los caracteres correctamente.
Las cadenas de comillas simples no tienen este problema, ya que para usar una variable $foo
en una cadena, tendríamos que escribir
''Hello ''. $foo .''!'';
en lugar de
"Hello $foo!";
Como podemos en las cuerdas dobles. 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 adjunten como en el ejemplo anterior), en lugar de interpretarlas como texto sin formato. Como ya no tenemos que escapar de la variable, podemos escaparnos solo con
''/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 usas o cuál es más fácil para el patrón.
TL; DR: Use /$
para cadenas de comillas simples como ''/Hello /$bob/is''
, y ///$
para cadenas de comillas dobles como "/Hello ///$bob/is"
.