неразрывное пространство 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 .

На самом деле документация об escape-последовательностях в PHP неверна. Когда вы используете синтаксис \xc2\xa0 , он ищет символ UTF-8. Но с синтаксисом \x{c2a0} он пытается преобразовать последовательность Unicode в кодированный символ UTF-8.

Неразрывное пространство U+00A0 (Unicode), но кодируется как C2A0 в UTF-8. Поэтому, если вы попробуете шаблон ~\x{00a0}~siu , он будет работать так, как ожидалось.

У меня есть предыдущие ответы 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>'; 

На мой взгляд, два кода делают разные вещи: первый \ xc2 \ xa0 заменит TWO символов, \ xc2 и \ xa0 ничем.

В кодировке utf-8 это оказывается кодовой точкой для U + 00A0

работает \ x {00A0}? Это должно быть представление для \ xc2 \ xa0

Я не использовал этот вариант ~\x{c2a0}~siu .

Varian \x{00A0} работает. Я не пробовал второй вариант, и вот результат:

Я попытался преобразовать его в hex и заменить свободное пространство 0xC2 0xA0 (c2a0) на пробел 0x20 (20) .

Код:

 $hex = bin2hex($item); $_item = str_replace('c2a0', '20', $hex); $item = hex2bin($_item);