2013-12-10 14 views
8

Chuỗi được đề cập có ký tự unicode bổ sung "\ ud84c \ udfb4". Theo javadoc, kết hợp regex nên được thực hiện ở cấp mã điểm chứ không phải cấp độ ký tự. Tuy nhiên, mã phân tách bên dưới coi đối tượng thay thế thấp (\ udfb4) là ký tự không phải từ và chia tách nó.Java 7, regexes và các ký tự unicode bổ sung

Tôi có thiếu gì đó không? Các lựa chọn thay thế khác để thực hiện chia tách các ký tự không phải là từ là gì? (Phiên bản Java "1.7.0_07")

Xin cảm ơn trước.

Pattern non_word_regex = Pattern.compile("[\\W]", Pattern.UNICODE_CHARACTER_CLASS); 
String a = "\u529f\u80fd\u0020\u7d76\ud84c\udfb4\u986f\u793a\u5ee3\u544a"; 
String b ="功能 絶顯示廣告"; 
System.out.print("original "+a+"\norginal hex "); 
for(char c : a.toCharArray()){ 
    System.out.print(Integer.toHexString((int)c)); 
    System.out.print(' '); 
} 
System.out.println(); 

String[] tokens = non_word_regex.split(a); 

for(int i =0; i< tokens.length; i++){ 
    String token = tokens[i]; 
    System.out.print(i+" "); 
    for(char c : token.toCharArray()){ 
     System.out.print(Integer.toHexString((int)c)); 
     System.out.print(' '); 
    } 
    System.out.println(); 
} 

Output:
gốc 功能 絶 顯示 廣告
gốc hex 529f 80fd 20 7d76 d84c dfb4 986f 793a 5ee3 544a
0 529f 80fd
1 7d76 d84c
2 986f 793a 5ee3 544a

Trả lời

9

Điều này trông giống như một lỗi trong công cụ regex. Nếu bạn sử dụng biểu thức \w, mọi thứ khớp chính xác, vẫn là một điểm mã đơn gồm hai ký tự. Điều này có thể dễ dàng được xác minh bằng cách chạy mã sau:

Pattern pattern = Pattern.compile("(?U)[\\w]"); 
String str = "功能 絶顯示廣告"; 

Matcher matcher = pattern.matcher(str); 
while (matcher.find()) { 
    System.out.println(matcher.toMatchResult().group()); 
} 

Tôi vừa thực hiện một cuộc điều tra và tôi có thể cho bạn biết vấn đề ở đâu. Nếu bạn nhìn vào phương pháp compile() trong java.util.regex.Pattern (bắt đầu trên dòng 1625), bạn sẽ thấy mã quét regex cho các ký tự bổ sung và quyết định có hỗ trợ chúng trong quá trình quét hay không.

Vấn đề với cách tiếp cận này là mã không tính đến thực tế là ngay cả khi regex không có các ký tự bổ sung, nó vẫn có thể khớp với chúng, như nó xảy ra trong trường hợp của bạn, ví dụ .

Giải pháp là để đưa ra một số regex mà chứa các ký tự bổ sung, nhưng họ không ảnh hưởng đến quá trình kết hợp. Tôi khuyên bạn nên sử dụng một cái gì đó vô tội như thế này:

Pattern nonWordRegex = Pattern.compile("(?U)(?!\uDB80\uDC00)[\\W]"); 

Phần (?!\uDB80\uDC00) thực hiện thủ thuật. Đây là một cái nhìn tiêu cực cho một nhân vật trong phạm vi riêng của các nhân vật bổ sung, có nghĩa là nhiều khả năng bạn sẽ không tìm thấy nó trong văn bản. Và thì đấy: động cơ regex nghĩ rằng có những nhân vật phụ trong mẫu hình, và bật hỗ trợ của họ!

+0

Thật không may, Matcher không giữ gìn ranh giới từ. Sử dụng "[^ \\ w]" dự đoán, cho kết quả tương tự như "[\\ W]" Tôi có nên đăng nó trên bảng java ở đâu đó không? – user3088039

+1

@ user3088039 Tôi vừa giải quyết vấn đề! Kiểm tra lại câu trả lời, tôi đã cập nhật nó. – Malcolm

+0

Bạn nghĩ rằng "(? U)" sẽ bật hỗ trợ ký tự bổ sung. Cảm ơn bạn đã tìm kiếm dưới bìa. Nó hoạt động rất đẹp. – user3088039

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