2010-03-12 24 views
11

Tôi có đoạn code sau trong một file php utf-8:php regex từ ranh giới tương ứng trong utf-8

var_dump(setlocale(LC_CTYPE, 'de_DE.utf8', 'German_Germany.utf-8', 'de_DE', 'german')); 
var_dump(mb_internal_encoding()); 
var_dump(mb_internal_encoding('utf-8')); 
var_dump(mb_internal_encoding()); 
var_dump(mb_regex_encoding()); 
var_dump(mb_regex_encoding('utf-8')); 
var_dump(mb_regex_encoding()); 
var_dump(preg_replace('/\bweiß\b/iu', 'weiss', 'weißbier')); 

Tôi muốn regex cuối cùng để thay thế chỉ từ đầy đủ và không bộ phận của từ.

Trên máy tính của cửa sổ của tôi, nó sẽ trả về:

string 'German_Germany.1252' (length=19) 
string 'ISO-8859-1' (length=10) 
boolean true 
string 'UTF-8' (length=5) 
string 'EUC-JP' (length=6) 
boolean true 
string 'UTF-8' (length=5) 
string 'weißbier' (length=9) 

Trên webserver (linux), tôi nhận được:

string(10) "de_DE.utf8" 
string(10) "ISO-8859-1" 
bool(true) 
string(5) "UTF-8" 
string(10) "ISO-8859-1" 
bool(true) 
string(5) "UTF-8" 
string(9) "weissbier" 

Như vậy, regex hoạt động như tôi mong đợi trên cửa sổ nhưng không phải trên linux .

Vì vậy, câu hỏi chính là, làm thế nào tôi nên viết regex của tôi để chỉ phù hợp ở ranh giới từ?

Câu hỏi phụ là làm thế nào tôi có thể cho các cửa sổ biết rằng tôi muốn sử dụng utf-8 trong ứng dụng php của mình.

Trả lời

16

Ngay cả trong chế độ UTF-8, viết tắt loại tiêu chuẩn như \w\b không nhận dạng Unicode. Bạn chỉ cần sử dụng shorthands Unicode, như bạn làm việc ra, nhưng bạn có thể làm cho nó một chút ít xấu xí bằng cách sử dụng lookarounds thay vì alternations: cũng

/(?<!\pL)weiß(?!\pL)/u 

Chú ý làm thế nào tôi rời khỏi dấu ngoặc nhọn ra khỏi lớp Unicode viết tắt; bạn có thể làm điều đó khi tên lớp bao gồm một chữ cái duy nhất.

+1

+1 - '\ w' và' \ b' có vẻ như hoạt động như mong đợi trong các phiên bản PHP gần đây nhưng chắc chắn không phải thứ bạn có thể dựa vào vì chúng có thể bị hỏng khi bạn triển khai ứng dụng của mình. –

+0

Cũng lưu ý câu trả lời được chấp nhận ở đây: http://stackoverflow.com/questions/4781898/regex-word-boundary-does-not-work-in-ut8-on-some-servers nếu bạn muốn sử dụng viết tắt unicode! –

3

đây là những gì tôi đã tìm thấy cho đến nay. Bằng cách viết lại các mẫu tìm kiếm và thay thế như thế này:

$before = '(^|[^\p{L}])'; 
$after = '([^\p{L}]|$)'; 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weißbier')); 
// Test some other cases: 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß')); 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß bier')); 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', ' weiß')); 

tôi nhận được kết quả mong muốn:

string 'weißbier' (length=9) 
string 'weiss' (length=5) 
string 'weiss bier' (length=10) 
string ' weiss' (length=6) 

trên cả hai cửa sổ máy tính chạy apache của tôi và trên tổ chức linux webserver chạy apache.

Tôi cho rằng có một số cách tốt hơn để thực hiện việc này.

Ngoài ra, tôi vẫn muốn thiết lập máy tính cửa sổ của mình thành utf-8.

0

Theo this comment, đó là lỗi trong PHP. Việc sử dụng \W thay vì \b có mang lại lợi ích gì không?

4

Guess này có liên quan đến Bug #52971

PCRE-Meta-Nhân vật như \b\w không làm việc với chuỗi unicode.

fixed in PHP 5.3.4

mở rộng PCRE: Sửa lỗi # 52.971 (PCRE-Meta-Nhân vật không làm việc với utf-8).

Các vấn đề liên quan