Hífen dentro de conjuntos em expressões regulares PHP
O hífen - também é um caractere especial dentro de []
(mas fora deles - não é). Se você precisa do próprio
hífen como um caractere - coloque-o onde
ele não será interpretado como um separador
de intervalo.
Por que isso é importante: você pode criar um intervalo
de caracteres sem perceber. Por exemplo,
assim - [:-@] - você acha que está
selecionando dois-pontos, hífen e arroba, mas na
verdade, resulta em um intervalo de caracteres entre
: e @. Este intervalo inclui
os seguintes caracteres: :, ;, ?,
<, =, >.
De onde eles vêm? Da tabela ASCII - o dois-pontos tem um número menor que o da arroba - e assim forma-se um intervalo. Ou seja, todos os intervalos são formados de acordo com a tabela ASCII (se desejar, você pode usar isso a seu favor).
Como lidar com isso: coloque o caractere hífen
onde ele certamente não será interpretado como
um caractere de intervalo, por exemplo, no início ou no final
(ou seja, depois de [ ou antes de ]).
Você também pode escapar o hífen - então
ele representará a si próprio, independentemente da
posição. Por exemplo, em vez de [:-@], escreva
[:\-@] - e não haverá mais um intervalo, mas
sim três caracteres - dois-pontos, hífen e arroba @.
Exemplo
No exemplo a seguir, o padrão de busca é:
dígito 1, depois uma letra de 'a'
a 'z', depois o dígito 2:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[a-z]2#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! 1-2 ! !'
Exemplo
Agora vamos escapar o hífen. Como resultado,
o padrão de busca é: dígito 1, depois
a letra 'a', ou hífen, ou a letra 'z',
depois o dígito 2:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[a\-z]2#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! ! 1c2 !'
Exemplo
Você pode simplesmente reposicionar o hífen, sem escapá-lo:
<?php
$str = '1a2 1-2 1c2 1z2';
$res = preg_replace('#1[az-]2#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! ! 1c2 !'
Exemplo
No exemplo a seguir, o padrão de busca é:
o primeiro caractere - são letras minúsculas ou
hífen '-', depois duas letras 'x':
<?php
$str = 'axx Axx -xx @xx';
$res = preg_replace('#[a-z-]xx#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! Axx ! @xx'
Exemplo
No exemplo a seguir, o padrão de busca é:
o primeiro caractere - são letras minúsculas, maiúsculas
ou hífen '-', depois duas letras
'x':
<?php
$str = 'axx Axx -xx @xx';
$res = preg_replace('#[a-zA-Z-]xx#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! ! ! @xx'
Exemplo
Você pode colocar o hífen entre dois intervalos - lá ele certamente não criará outro intervalo:
<?php
$str = 'axx 9xx -xx @xx';
$res = preg_replace('#[a-z-0-9]xx#', '!', $str);
?>
Como resultado, será armazenado na variável o seguinte:
'! ! ! @xx'
Problemas práticos
Dada a string:
<?php
$str = 'xaz xBz xcz x-z x@z';
?>
Encontre todas as strings seguindo o padrão:
letra 'x', letra maiúscula ou minúscula
ou hífen, letra 'z'.
Dada a string:
<?php
$str = 'xaz x$z x-z xcz x+z x%z x*z';
?>
Encontre todas as strings seguindo o padrão:
letra 'x', depois ou cifrão, ou
hífen ou mais, depois letra 'z'.