Crie um arquivo test.php
e execute o código abaixo (salve o arquivo com conjunto de caracteres UTF-8).
echo preg_replace("/./","X","Á");
Você obterá XX
(deveria retornar apenas um X
, mas aqui está o primeiro bug). O PHP está fazendo algumas coisas estranhas aqui com multibyte.
Agora execute este código:
echo preg_replace("/.$/","X","Á");
Você obterá �X
. Isso está relacionado ao bug acima, mas por algum motivo o primeiro char é corrompido.
De qualquer forma, há uma maneira fácil de resolver esse problema? Minha regex atual é muito mais complicada do que a acima, é claro que a acima é inútil, mas é o mínimo para reproduzir o bug.
O problema está acontecendo porque a
preg_replace
função substitui cada caractere na string de entrada por um"X"
. O caractere"Á"
é tratado como um caractere multibyte no PHP, o que significa que ele é armazenado como mais de um byte (ou parte) na memória.Quando
preg_replace
usa o padrão"/./"
, ele corresponde a cada byte separadamente, não ao"Á"
caractere inteiro. Então, em vez de substituir"Á"
por um"X"
, ele substitui cada parte (byte) de"Á"
por"X"
, resultando em"XX"
.Para consertar você deve usar uma expressão regular que funcione com caracteres multibyte. Assim
Explicação : Adicionar o
u
modificador informa ao PHP para tratar a string como UTF-8.O problema com seu segundo código é similar ao primeiro. Aqui está a correção para isso.
Execução online : https://3v4l.org/RLYma