Неразрывное пространство utf-8 0xc2a0 и preg_replace странное поведение
В моей строке у меня есть неиспользуемое пространство utf-8 (0xc2a0), и я хочу заменить его чем-то другим.
Когда я использую
$str=preg_replace('~\xc2\xa0~', 'X', $str);
он работает нормально.
Но когда я использую
$str=preg_replace('~\x{C2A0}~siu', 'W', $str);
неразрывное пространство не найдено (и заменено).
Почему? Что не так со вторым регулярным выражением?
Формат \x{C2A0}
правильный, также я использовал флаг u
.
Ответы
Ответ 1
Собственно, документация об escape-последовательностях в PHP неверна. Когда вы используете синтаксис \xc2\xa0
, он ищет символ UTF-8. Но с синтаксисом \x{c2a0}
он пытается преобразовать последовательность Unicode в кодированный символ UTF-8.
Неразрывное пространство U+00A0
(Unicode), но кодированное как C2A0
в UTF-8. Поэтому, если вы попробуете шаблон ~\x{00a0}~siu
, он будет работать, как ожидалось.
Ответ 2
У меня есть предыдущие ответы aggegate, поэтому люди могут просто скопировать/вставить следующий код, чтобы выбрать свой любимый метод:
$some_text_with_non_breaking_spaces = "some text with 2 non breaking spaces at the beginning";
echo 'Qty non-breaking space : ' . substr_count($some_text_with_non_breaking_spaces, "\xc2\xa0") . '<br>';
echo $some_text_with_non_breaking_spaces . '<br>';
# Method 1 : regular expression
$clean_text = preg_replace('~\x{00a0}~siu', ' ', $some_text_with_non_breaking_spaces);
# Method 2 : convert to bin -> replace -> convert to hex
$clean_text = hex2bin(str_replace('c2a0', '20', bin2hex($some_text_with_non_breaking_spaces)));
# Method 3 : my favorite
$clean_text = str_replace("\xc2\xa0", " ", $some_text_with_non_breaking_spaces);
echo 'Qty non-breaking space : ' . substr_count($clean_text, "\xc2\xa0"). '<br>';
echo $clean_text . '<br>';
Ответ 3
Два кода делают разные вещи, на мой взгляд: первый \xc2\xa0 заменит TWO символов, \xc2 и\xa0 ничем.
В кодировке utf-8 это оказывается кодовым пунктом для U + 00A0
работает\x {00A0}? Это должно быть представление для\xc2\xa0
Ответ 4
Я не использовал этот вариант ~\x{c2a0}~siu
.
Varian \x{00A0}
работает. Я не пробовал второй вариант, и вот результат:
Я попытался преобразовать его в шестнадцатеричный и заменить свободное пространство 0xC2 0xA0 (c2a0)
на пробел 0x20 (20)
.
код:
$hex = bin2hex($item);
$_item = str_replace('c2a0', '20', $hex);
$item = hex2bin($_item);