2010-06-29 34 views
7

Tôi có một chuỗi UTF8 với sự kết hợp dấu phụ. Tôi muốn khớp nó với trình tự regex \w. Nó phù hợp với các ký tự có dấu trọng âm, nhưng không phải nếu có một ký tự latin với sự kết hợp dấu phụ.Python regex w không khớp với dấu phụ?

>>> re.match("a\w\w\wz", u"aoooz", re.UNICODE) 
<_sre.SRE_Match object at 0xb7788f38> 
>>> print u"ao\u00F3oz" 
aoóoz 
>>> re.match("a\w\w\wz", u"ao\u00F3oz", re.UNICODE) 
<_sre.SRE_Match object at 0xb7788f38> 
>>> re.match("a\w\w\wz", u"aoo\u0301oz", re.UNICODE) 
>>> print u"aoo\u0301oz" 
aóooz 

(Hình như processer SO markdown đang gặp rắc rối với các dấu kết hợp ở trên, nhưng có một trên dòng cuối cùng)

Liệu có cách nào để phù hợp với dấu kết hợp với \w ? Tôi không muốn bình thường hóa văn bản bởi vì văn bản này là từ tên tập tin, và tôi không muốn phải làm một toàn bộ 'tên tập tin bình thường unicode' được nêu ra. Đây là Python 2.5.

Trả lời

5

Tôi vừa mới nhận thấy gói "regex" mới trên pypi. (Nếu tôi hiểu chính xác, nó là một phiên bản thử nghiệm của một gói mới mà một ngày nào đó sẽ thay thế gói stdlib re).

Dường như có (trong số những thứ khác) nhiều khả năng liên quan đến unicode hơn. Ví dụ, nó hỗ trợ \X, được sử dụng để phù hợp với một grapheme đơn (cho dù nó sử dụng kết hợp hay không). Nó cũng hỗ trợ kết hợp trên các thuộc tính unicode, các khối và tập lệnh, vì vậy bạn có thể sử dụng \p{M} để tham chiếu đến các dấu kết hợp. Số \X được đề cập trước đó tương đương với \P{M}\p{M}* (một ký tự KHÔNG phải là dấu kết hợp, tiếp theo là số không hoặc nhiều dấu kết hợp).

Lưu ý rằng điều này làm cho \X nhiều hơn hoặc ít hơn tương đương unicode ., không phải là \w, vì vậy trong trường hợp của bạn, \w\p{M}* là những gì bạn cần.

Bây giờ là một gói không phải là stdlib và tôi không biết nó sẵn sàng như thế nào (và nó không có bản phân phối nhị phân), nhưng bạn có thể muốn thử nó có vẻ là câu trả lời dễ nhất/chính xác nhất cho câu hỏi của bạn. (Nếu không, tôi nghĩ rằng bạn xuống sử dụng một cách rõ ràng phạm vi ký tự, như được mô tả trong bình luận của tôi cho câu trả lời trước đó).

Xem thêm this page với thông tin về cụm từ thông dụng unicode, cũng có thể chứa một số thông tin hữu ích cho bạn (và có thể làm tài liệu cho một số điều được triển khai trong gói regex).

1

Bạn có thể sử dụng unicodedata.normalize để soạn dấu phụ kết hợp thành một ký tự unicode.

>>> import re 
>>> from unicodedata import normalize 
>>> re.match(u"a\w\w\wz", normalize("NFC", u"aoo\u0301oz"), re.UNICODE) 
<_sre.SRE_Match object at 0x00BDCC60> 

Tôi biết bạn nói bạn không muốn bình thường hóa, nhưng tôi không nghĩ sẽ có vấn đề với giải pháp này vì bạn chỉ bình thường hóa chuỗi để đối sánh và không có để thay đổi tên tập tin hoặc một cái gì đó.

+1

Có, điều đó sẽ cho tôi biết nếu tôi có một trận đấu, nhưng sau khi thực hiện trận đấu, tôi rút ra các nhóm phù hợp và sau đó làm công cụ với họ. Nếu tôi sử dụng cách tiếp cận của bạn, thì các byte tôi có sau đó sẽ không phải là các byte giống như trong tên tệp – Rory

+0

Tôi hiểu. Bạn có biết liệu các chuỗi có nhất quán trong việc sử dụng các dấu phụ kết hợp (luôn kết hợp hoặc ít nhất là luôn kết hợp hay không trong một chuỗi đơn)? Nếu có, bạn có thể bình thường hóa kết quả thành NFC hoặc NFD một lần nữa nếu cần. Nếu không, tôi nghĩ bạn sẽ phải sử dụng các thủ thuật để phát hiện vị trí kết hợp dấu phụ trong chuỗi gốc, và cố gắng sử dụng thông tin đó để phân tách chỉ các ký tự cần thiết (dĩ nhiên sẽ có nhiều công việc hơn là chỉ phân tách mọi thứ hoặc không có gì). – Steven

+0

Hoặc có thể chỉ cần thay đổi biểu thức và sử dụng các phạm vi cho các dấu phụ kết hợp mà bạn quan tâm và sử dụng một cái gì đó như \ w [\ u0300- \ u036F]? thay vì chỉ \ w – Steven

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