вырезать многобайтовое пустое пространство из строки PHP

Я пытаюсь использовать preg_replace для устранения японского полного пробела "   "из строкового ввода, но я получаю поврежденную многобайтную строку.

Я предпочел бы preg_replace вместо str_replace. Вот пример кода:

 $ keywords = 'ラ メ 単 色';
 $ keywords = str_replace (array ('', ''), '', urldecode ($ keywords));  // выходы: 'ラ メ 単 色'

 $ keywords = preg_replace ("@ [] @", '', urldecode ($ keywords));  // выходы: '      単 色'

Кто-нибудь знает, почему это так и как исправить эту ситуацию?

Добавьте флаг u в ваше регулярное выражение. Это делает механизм RegEx обрабатывать входную строку как UTF-8.

 $keywords = preg_replace("@[  ]@u", ' ',urldecode($keywords)); // outputs :'ラメ単色' 

CodePad .

Причина, по которой он искажает строку, заключается в том, что для механизма RegEx ваши замещающие символы, 20 (пробел) или e3 80 80 (IDEOGRAPHIC SPACE) не рассматриваются как два символа, а отдельные байты 20 , e3 и 80 .

Когда вы просматриваете последовательность байтов вашей строки для сканирования, получаем e3 80 80 e3 83 a9 e3 83 a1 e5 8d 98 e8 89 b2 . Мы знаем, что первый символ – это ИДЕОГРАФИЧЕСКОЕ ПРОСТРАНСТВО, но поскольку PHP обрабатывает его как последовательность байтов, он выполняет замену по отдельности из первых четырех байтов, поскольку они соответствуют отдельным байтам, которые сканирует механизм регулярных выражений.

Что касается mangling, который приводит к (ЗАМЕНА ХАРАКТЕРА), мы можем видеть, что это происходит, потому что байт e3 присутствует далее вдоль строки. Байт e3 является стартовым байтом японского символа длиной три байта, например e3 83 a9 (KATAKANA LETTER RA). Когда этот ведущий e3 заменяется на 20 (пробел), он больше не становится действительной последовательностью UTF-8.

Когда вы включаете флаг u , механизм RegEx обрабатывает строку как UTF-8 и не будет обрабатывать ваши символы в вашем классе символов на основе каждого байта.

Чтобы избежать дополнительных проблем, также рассмотрите возможность установки внутреннего кодирования явно на решение mb_ *:

 mb_internal_encoding("UTF-8"); 

Всегда хорошо разбираться в документации. Я узнал, что связанная с preg_ * функция не оптимизирована для атрибута mulitbyte. Вместо этого предполагается использовать функции mb_ereg_ * и mb_ *. Я решил эту небольшую проблему, переделав код на что-то вроде:

 $ keywords = 'ラ メ 単 色';
 $ pattern = "" / * ascii whitespace * /.  "/ * многобайтовые пробелы * /;
 $ keywords = trim (
     mb_ereg_replace ("[{$ pattern}] +", '', urldecode ($ keywords)));  // выходы: 'ラ メ 単 色' 

Спасибо всем!

Использовать это

 $keywords = preg_replace('/\s+/', ' ',urldecode($keywords));