El guion dentro de conjuntos en expresiones regulares de PHP
El guion - también es un carácter especial dentro de []
(pero fuera de ellos - no). Si necesitas el guion como símbolo - colócalo allí,
donde no será interpretado como un separador de rango.
Por qué esto es importante: puedes crear un rango de caracteres
sin darte cuenta. Por ejemplo,
así - [:-@] - tú crees que estás
seleccionando dos puntos, guion y arroba, pero en
realidad resulta un rango de caracteres entre
: y @. Este rango incluye
los siguientes caracteres: :, ;, ?,
<, =, >.
¿De dónde salieron? De la tabla ASCII - los dos puntos tienen un número menor que la arroba - y se forma un rango. Es decir, todos los rangos se forman según la tabla ASCII (si se desea, se puede aprovechar esto).
Cómo solucionarlo: coloca el carácter guion
allí donde definitivamente no será interpretado como
un rango, por ejemplo, al principio o al final
(es decir, después de [ o antes de ]).
También se puede escapar el guion - entonces
representará a sí mismo independientemente de la
posición. Por ejemplo, en lugar de [:-@] escribir
[:\-@] - y ya no habrá un rango, sino
tres caracteres - dos puntos, guion y arroba @.
Ejemplo
En el siguiente ejemplo el patrón de búsqueda es este:
dígito 1, luego letra de 'a'
a 'z', luego dígito 2:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[a-z]2#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! 1-2 ! !'
Ejemplo
Ahora escapemos el guion. Como resultado
el patrón de búsqueda es este: dígito 1, luego
letra 'a', o guion, o letra 'z',
luego dígito 2:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[a\-z]2#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! ! 1c2 !'
Ejemplo
Se puede simplemente cambiar la posición del guion, sin escaparlo:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[az-]2#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! ! 1c2 !'
Ejemplo
En el siguiente ejemplo el patrón de búsqueda es este:
primer carácter - letras minúsculas o
guion '-', luego dos letras 'x':
<?php
$str = 'axx Axx -xx @xx';
$res = preg_replace('#[a-z-]xx#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! Axx ! @xx'
Ejemplo
En el siguiente ejemplo el patrón de búsqueda es este:
primer carácter - letras minúsculas, mayúsculas
o guion '-', luego dos letras
'x':
<?php
$str = 'axx Axx -xx @xx';
$res = preg_replace('#[a-zA-Z-]xx#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! ! ! @xx'
Ejemplo
Se puede colocar el guion entre dos rangos - allí definitivamente no creará otro rango:
<?php
$str = 'axx 9xx -xx @xx';
$res = preg_replace('#[a-z-0-9]xx#', '!', $str);
?>
Como resultado, en la variable se guardará lo siguiente:
'! ! ! @xx'
Problemas prácticos
Dada la cadena:
<?php
$str = 'xaz xBz xcz x-z x@z';
?>
Encuentra todas las cadenas según el siguiente patrón:
letra 'x', letra mayúscula o minúscula
o guion, letra 'z'.
Dada la cadena:
<?php
$str = 'xaz x$z x-z xcz x+z x%z x*z';
?>
Encuentra todas las cadenas según el siguiente patrón:
letra 'x', luego signo de dólar, o
guion o signo más, luego letra 'z'.