2016-02-13 20 views
6

Có cách nào trong regex để chỉ định kết quả phù hợp cho một ký tự có dấu phụ cụ thể không? Hãy nói một giọng nghiêm trọng ví dụ. Các chặng đường dài để làm điều này là để đi đến Wikipedia page on the grave accent, sao chép tất cả các ký tự nó cho thấy, sau đó tạo ra một lớp nhân vật ra trong số họ:Ký tự đối sánh regex với dấu phụ cụ thể

/[àầằèềḕìǹòồṑùǜừẁỳ]/i 

Đó là khá tẻ nhạt. Tôi đã hy vọng cho một tài sản Unicode như \p{hasGraveAccent}, nhưng tôi không thể tìm thấy bất cứ điều gì như thế. Tìm kiếm một giải pháp chỉ xuất hiện với các câu hỏi từ những người cố gắng để phù hợp với các nhân vật trong khi bỏ qua dấu phụ, trong đó bao gồm việc thực hiện một bình thường hóa của một số loại, mà không phải là những gì tôi muốn.

+0

Nếu đó là ký tự kết hợp, có thể thực hiện được bằng cách [tạo danh sách các điểm mã unicode] (http://stackoverflow.com/questions/17051732/algorithm-to-check-for-combining-characters-in-unicode). – kba

+0

Tạo một lớp nhân vật trong số các chữ cái đơn không đáng tin cậy và sẽ không hoạt động.Nó sẽ chỉ hoạt động đối với các chữ cái được chuẩn bị trước phù hợp với các chuỗi NFC (dạng chuẩn hóa được tạo thành). Hầu hết các ký tự có hai hoặc nhiều dấu phụ không có ký tự được sắp xếp trước. I E. chúng bao gồm nhiều hơn một điểm mã (= ký tự trong bài phát biểu Unicode). Nếu bạn sao chép và dán chúng vào một lớp nhân vật thì dấu phụ vẫn là một ký tự đơn và sẽ khớp với cùng một dấu phụ trong chuỗi đích. –

Trả lời

0

Đó là một câu hỏi khó, nhưng có thể. Đầu tiên, bạn phải chuẩn hóa chuỗi unicode thành một trong 4 dạng. Thông tin về chuẩn hóa là here và bản đồ các ví dụ về ký tự có các chuẩn hóa khác nhau là here và biểu đồ tốt cho các ký tự được chuẩn hóa là here. Về cơ bản, bình thường hóa chỉ đảm bảo tất cả các ký tự có cùng định dạng khi xử lý dấu phụ. Golang có hỗ trợ tuyệt vời cho điều này, và hầu hết tất cả các ngôn ngữ nên chứa các thư viện để làm điều này.

Vì vậy, ví dụ của tôi, chuyển đổi chuỗi của bạn thành "Chuẩn hóa biểu mẫu D" (NFD) và utf32, vì vậy tất cả các ký tự unicode là các điểm mã của chúng trong 4 byte.

Tất cả các ký tự dấu phụ cho dấu trọng âm có 0x0300 bên cạnh ký tự. Vì vậy, bạn có thể thực hiện tìm kiếm biểu thức chính quy ở chế độ ascii (KHÔNG chế độ unicode) cho ....\x00\x00\x03\x00. Từ đó bạn phải trích xuất vị trí rune của nó. Điều đó có thể được thực hiện với các phương thức khác nhau tùy thuộc vào mã hóa bạn đang sử dụng.

Vì vậy, nếu bạn truy cập vào bộ phận 4, bạn sẽ biết ký tự hợp lệ của nó.

Bên cạnh đó, không có nhóm nhân vật perl chính thức nào để thực hiện việc này.

Perl mã như một ví dụ:

use Encode; 
use Unicode::Normalize; 

$StartUTF8='xàaâèaê'; 
$PerlEncoded=decode('utf8', $StartUTF8); 
$PerlNormalized=NFD($PerlEncoded); 
$UTF32Normalized=encode('utf32', $PerlNormalized); 

while($UTF32Normalized =~ /(....\x00\x00\x03\x00)/gs) { 
    $Pos=pos($UTF32Normalized)-8; 
    if($Pos%4==0) { 
     print("$Pos\n"); 
    } 
} 

Nhưng vào thời điểm này, bạn cũng có thể chỉ được thực hiện một vòng lặp for trong các nhân vật: - \

Tôi cũng đã cố gắng phù hợp mà không cần vị trí kiểm tra bằng cách sử dụng // c, nhưng vì lý do nào đó nó sẽ không hoạt động.

/^(?:....)*?(....\x00\x00\x03\x00)/gcs

+0

Không có điểm chuyển đổi thành UTF32 (và, nếu bạn định giả định kết quả là UTF-32LE, bạn nên chuyển đổi thành thay vì để nó thành cơ hội). Ngoài ra, giả thiết rằng dấu trọng âm ngay sau ký tự cơ sở có thể không chính xác khi glyph chứa nhiều dấu phụ. – rici

+0

Thật vậy. Đó là nghiên cứu và thử nghiệm không có kết quả – Dakusan

1

Có thể có một số hạn chế.

#!perl 

use strict; 
use warnings; 

use Encode; 
use Unicode::Normalize; 
use charnames qw(); 
use utf8; # source is utf-8 

binmode(STDOUT, ":utf8"); # print in utf-8 

my $utf8_string = 'xàaâèaêòͤ'; 

my $nfd_string = NFD($utf8_string); # decompose 

my @chars_with_grave = $nfd_string =~ 
    m/ 
    (
     \p{L}   # one letter 
     \p{M}*   # 0 or more marks 
     \N{COMBINING GRAVE ACCENT} 
     \p{M}*   # 0 or more marks 
    ) 
    /xmsg; 

print join(', ',@chars_with_grave), "\n"; 

này in

$ perl utf_match_grave.pl 
à, è, òͤ 

LƯU Ý: Các nhân vật trong lĩnh vực chỉnh sửa được hiển thị một cách chính xác như kết hợp, nhưng stackoverflow làm cho họ sai tách.

Cần thư làm ký tự cơ sở. Thay đổi regex cho các ký tự cơ bản khác. Đánh dấu \p{M} có thể không chính xác những gì bạn muốn, cần được cải thiện.

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