Barra invertida extra necessária no padrão PHP regexp
Pergunta
Ao testar uma resposta para pergunta de outro usuário Encontrei algo que não entendo.O problema era substituir todos os literais \t
\n
\r
caracteres de uma string com um único espaço.
Agora, o primeiro padrão que tentei foi:
/(?:\\[trn])+/
o que surpreendentemente não funcionou.Tentei o mesmo padrão em Perl e funcionou bem.Após algumas tentativas e erros, descobri que o PHP deseja 3 ou 4 barras invertidas para que esse padrão corresponda, como em:
/(?:\\\\[trn])+/
ou
/(?:\\\[trn])+/
esses padrões - para minha surpresa - funcionam.Por que essas barras invertidas extras são necessárias?
Solução
Você precisa de 4 barras invertidas para representar 1 em regex porque:
- 2 barras invertidas são usadas para remover o escape em uma string (
"\\\\" -> \\
) - 1 barra invertida é usada para remover o escape no mecanismo regex (
\\ -> \
)
Do documento PHP,
escapar de qualquer outro caractere resultará na impressão da barra invertida também1
Daí para \\\[
,
- 1 barra invertida é usada para remover o escape do
\
, um fica porque\[
é inválido ("\\\[" -> \\[
) - 1 barra invertida é usada para remover o escape no mecanismo regex (
\\[ -> \[
)
Sim, funciona, mas não é uma boa prática.
Outras dicas
Seus trabalhos em Perl porque você passa isso diretamente como padrão regex /(?:\\[trn])+/
Mas no PHP, você precisa passar como string, portanto, precisa de escapar extra para a própria barra.
"/(?:\\\\[trn])+/"
O regex para corresponder a uma única barra de barriga se tornaria '//' como um String php preg
A expressão regular é apenas /(?:\\[trn])+/
. Mas como você precisa escapar das barras de barriga em declarações de cordas, cada barra de barriga deve ser expressa com \\
:
"/(?:\\\\[trn])+/"
'/(?:\\\\[trn])+/'
Apenas três backspaces também funcionam porque o PHP não conhece a sequência de fuga \[
e ignora. Então \\
se tornará \
mas \[
ficará \[
.
Use str_preplace!
$code = str_replace(array("\t","\n","\r"),'',$code);
Deve fazer o truque