2012-10-11 22 views
28

Trong chuỗi của tôi, tôi có utf-8 không phá vỡ không gian (0xc2a0) và tôi muốn thay thế nó bằng cái gì khác.không phá vỡ utf-8 0xc2a0 không gian và preg_replace hành vi lạ

Khi tôi sử dụng

$str=preg_replace('~\xc2\xa0~', 'X', $str); 

nó hoạt động OK.

Nhưng khi tôi sử dụng

$str=preg_replace('~\x{C2A0}~siu', 'W', $str); 

không gian không bị phá hủy không được tìm thấy (và thay thế).

Tại sao? Điều gì là sai với regexp thứ hai?

Định dạng \x{C2A0} là chính xác, tôi cũng sử dụng cờ u.

+0

Có thể là vì '$ str' không phải là unicode chuỗi. – YOU

Trả lời

46

Trên thực tế, tài liệu về các chuỗi thoát trong PHP là sai. Khi bạn sử dụng cú pháp \xc2\xa0, nó sẽ tìm kiếm ký tự UTF-8. Nhưng với cú pháp \x{c2a0}, nó cố chuyển đổi chuỗi Unicode thành ký tự mã hóa UTF-8.

Không gian không vi phạm là U+00A0 (Unicode) nhưng được mã hóa là C2A0 bằng UTF-8. Vì vậy, nếu bạn thử với mẫu ~\x{00a0}~siu, nó sẽ hoạt động như mong đợi.

+0

Có, \ x {00a0} hoạt động, cảm ơn bạn. – DamirR

+1

Xin chào Newbo. Câu trả lời của bạn làm việc cho tôi, nhưng tôi vẫn không hiểu tại sao. Có phải vì my nbsp không phải là UTF-8 không? Dữ liệu của tôi đến từ một bảng cơ sở dữ liệu với bộ ký tự utf8_general_ci, vì vậy nó phải là UTF-8 (character_set_client và character_set_connection của tôi cũng là UTF-8). Bạn có một liên kết để biết thêm thông tin về điều này? Cảm ơn. –

+3

[Bài viết này] (http://rrn.dk/the-difference-between-utf-8-and-unicode) là điều tuyệt vời để hiểu thêm về chủ đề này. Ngoài ra còn có [câu hỏi SO này] (http://stackoverflow.com/questions/3951722/whats-the-difference-between-unicode-and-utf8) trong đó bài viết cũ đã được sao chép/dán. –

3

Hai mã làm những việc khác nhau theo ý kiến ​​của tôi: \ xc2 \ xa0 đầu tiên sẽ thay thế HAI ký tự, \ xc2 và \ xa0 không có gì.

Trong utf-8 mã hóa, điều này sẽ xảy ra là các điểm mã cho U + 00A0

không \ x {00A0} làm việc? Đây phải là đại diện cho \ xc2 \ xa0

+0

\ x {00a0} hoạt động, cảm ơn bạn. – DamirR

1

Tôi không làm việc biến thể này ~\x{c2a0}~siu.

Varian \x{00A0} hoạt động. Tôi đã không thử tùy chọn thứ hai và đây là kết quả:

Tôi đã cố chuyển đổi thành hex và thay thế không gian trống 0xC2 0xA0 (c2a0) thành không gian 0x20 (20).

Code:

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

Cảm ơn, công trình ... – realmag777

10

Tôi đã câu trả lời trước aggegate để mọi người có thể chỉ cần sao chép/dán mã sau đây để lựa chọn phương pháp ưa thích của họ:

$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>';