![](/img/trans.png)
[英]How to write regular expression matching all unicode characters in Python?
[英]Python unicode regular expression matching failing with some unicode characters -bug or mistake?
我試圖在Python 2.7.3中使用帶有Unicode編碼的Devnagari文本的re
模塊。 我已將from __future__ import unicode_literals
添加到我的代碼頂部,因此所有字符串文字都應該是unicode對象。
但是,我遇到了Python正則表達式匹配的一些奇怪問題。 例如,考慮這個名字:“किशोरी”。 這是一個(拼寫錯誤的)名字,用印地語,由我的一個用戶輸入。 任何印地語讀者都會認為這是一個詞。
以下內容返回匹配,因為它應該:
re.search("^[\\w\\s][\\w\\s]*","किशोरी",re.UNICODE)
但這不是:
re.search("^[\\w\\s][\\w\\s]*$","किशोरी",re.UNICODE)
一些探險者發現該字符串中只有一個字符,字符0915(क)被識別為屬於\\ w字符類。 這是不正確的,因為“派生核心屬性”上的Unicode字符數據庫文件將此字符串中的其他字符(我沒有全部檢查過)列為字母字符 - 事實上它們確實如此。
這只是Python實現中的一個錯誤嗎? 我可以通過手動將所有Devnagari字母數字字符定義為字符范圍來解決這個問題,但這會很痛苦。 或者我做錯了什么?
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import unicodedata
import re
import regex # $ pip install regex
word = "किशोरी"
def test(re_):
assert re_.search("^\\w+$", word, flags=re_.UNICODE)
print([unicodedata.category(cp) for cp in word])
print(" ".join(ch for ch in regex.findall("\\X", word)))
assert all(regex.match("\\w$", c) for c in ["a", "\u093f", "\u0915"])
test(regex)
test(re) # fails
輸出顯示"किशोरी"
中有6個代碼點,但只有3個用戶感知的字符(擴展的字形集群)。 打破角色里面的單詞是錯誤的。 Unicode文本分段說:
字形 邊界 ,線邊界和句子邊界不應出現在字形集群中 :換句話說,字形集群應該是與確定這些其他邊界的過程相關的原子單元。
在這里,進一步強調我的
字邊界\\b
被定義為文檔中從\\w
到\\W
(或反向)的過渡:
請注意,正式地,\\ b被定義為\\ w和\\ W字符之間的邊界(反之亦然),或者在\\ w和字符串的開頭/結尾之間,...
因此,形成單個字符的所有代碼點都是\\w
或者它們都是\\W
在這種情況下, "किशोरी"
匹配^\\w{6}$
。
來自Python 2中\\w
的文檔 :
如果設置了UNICODE,則這將匹配字符[0-9_]以及Unicode字符屬性數據庫中分類為字母數字的任何字符 。
在Python 3中 :
匹配Unicode字符; 這包括大多數可以成為任何語言單詞的一部分的字符,以及數字和下划線。
從regex
文檔:
'word'字符的定義( 問題#1693050 ):
已經為Unicode擴展了“單詞”字符的定義。 它現在符合http://www.unicode.org/reports/tr29/上的Unicode規范。 這適用於\\ w,\\ W,\\ b和\\ B.
據unicode.org U+093F
( DEVANAGARI VOWEL SIGN I
)可以是alnum和字母所以regex
也是正確的考慮\\w
即使我們遵循並非基於單詞邊界定義。
從字符圖:
ि
U + 093F DEVANAGARI VOWEL SIGN I
一般字符屬性
在Unicode中:1.1 Unicode類別: Mark,Spacing Combining
因此,從技術上講,這不是一封信,即使使用re.UNICODE
也不屬於\\w
。 您可以嘗試使用帶有Unicode字符屬性的regex
來包含這些類型的字符。
我測試了以下內容:
import unicodedata
for c in "किशोरी":
print unicodedata.category(c)
print unicodedata.name(c)
在我的情況下顯示:
Lo
DEVANAGARI LETTER KA
Mc
DEVANAGARI VOWEL SIGN I
Lo
DEVANAGARI LETTER SHA
Mc
DEVANAGARI VOWEL SIGN O
Lo
DEVANAGARI LETTER RA
Mc
DEVANAGARI VOWEL SIGN II
Unicode的東西很難調試,因為復制和粘貼會弄亂數據,我不知道印地文。 但在某些語言中,您可以在unicode中以不同方式編碼字符。 是否有可能在匹配之前必須以某種方式規范化字符串? 對我而言,元音符號與\\w
不匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.