2009-12-02 75 views
48

Perl和其他一些當前正則表達式引擎在正則表達式中支持Unicode屬性,例如類別。例如。在Perl中,您可以使用\p{Ll}來匹配任意小寫字母,或p{Zs}以用於任何空格分隔符。我在Python的2.x和3.x行中都沒有看到對此的支持(帶有遺憾)。是否有人知道獲得類似效果的好策略?歡迎使用本土解決方案。匹配Unicode屬性的Python正則表達式

+10

實際上,Perl支持所有的** Unicode屬性,而不僅僅是一般的類別。例子包括:\ p {Block = Greek},\ p {Script = Armenian},\ p {General_Category = Uppercase_Letter},\ p {White_Space},\ p {Alphabetic},\ p {Math},\ p {Bidi_Class = Right_to_Left},\ p {Word_Break = A_Letter },\ p {Numeric_Value = 10},\ p {Hangul_Syllable_Type = Leading_Jamo},\ p {Sentence_Break = SContinue}只有Perl和ICU的正則表達式才能涵蓋完整的Unicode屬性。每個人都會涉及一小部分,通常對於最小的Unicode工作來說還不夠。 – tchrist 2011-04-25 23:03:07

回答

22

您是否試過Ponyguruma,一個Python與Oniguruma正則表達式引擎綁定?在該引擎中,您可以簡單地說\p{Armenian}以匹配亞美尼亞字符。 \p{Ll}\p{Zs}也可以。

+2

這個模塊與Python re模塊有不一樣的API – 2012-05-20 20:06:47

+7

最後承諾Ponyguruma模塊顯然是2010年( http://dev.pocoo.org/hg/sandbox/ponyguruma)而PyPI上的Python正則表達式模塊是積極開發的:http://pypi.python.org/pypi/regex – RichVel 2013-09-18 13:04:20

4

你說得對,Python屬性類不被Python正則表達式解析器支持。

如果你想做一個很好的黑客,這通常是有用的,你可以創建一個預處理器,掃描一個字符串這樣的類令牌(\p{M}或其他),並用相應的字符集替換它們,這樣例如,\p{M}將變爲[\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F],並且\P{M}將變爲[^\u0300–\u036F\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]

人們會感謝你。 :)

+1

正確的是,創造人物課程橫跨了我的想法。但大約有40個類別,你最終會生成80個類,這不包括unicode腳本,塊,平面和其他類。可能值得一個小開源項目,但仍然是一個維護噩夢。我剛剛發現re.VERBOSE不適用於字符類,所以這裏沒有評論或空白空間來幫助可讀性... – ThomasH 2009-12-02 15:17:51

2

請注意,雖然\p{Ll}在Python正則表達式中沒有等效,但\p{Zs}應覆蓋'(?u)\s'(?u),正如文檔所說:「使\ w,\ w,\ b,\ B,\ d,\ D,\ s和\ S依賴於Unicode字符屬性數據庫。」和\s表示任何間距字符。

+0

你是對的。問題是,'(?u)\ s'大於'\ p {Zs}',包括例如新隊。所以如果你真的只想匹配空間分隔符,前者會過度生成。 – ThomasH 2009-12-07 21:32:49

+3

@ThomasH:要獲得「空格,除非不換行」,您可以使用雙否定字符類:'(?u)[^ \ S \ n]' – bukzor 2012-03-22 22:12:01

6

可以精心上每個字符使用unicodedata:

import unicodedata 

def strip_accents(x): 
    return u''.join(c for c in unicodedata.normalize('NFD', x) if unicodedata.category(c) != 'Mn') 
+0

謝謝。雖然外面的正則表達式,這可能是某些情況下可行的替代方案。 – ThomasH 2010-11-13 21:09:27

+0

似乎Python'unicodedata'模塊目前不包含例如字符的腳本或Unicode塊。另請參閱https://stackoverflow.com/questions/48058402/unicode-table-information-about-a-character-in-python/48060112#48060112 – tripleee 2018-01-10 06:44:17

52

regex模塊(到標準re模塊的替代)支持帶有\p{}語法的Unicode編碼點的屬性。

+1

不確定''\ p {}''支持的完整性如何,但是這個模塊是積極開發的,並且最終應該替換內置的''re''模塊:參見http://pypi.python.org/pypi/regex – RichVel 2013-09-18 13:05:42

+4

+1:'regex'是stdlib的一個直接替代品're'模塊。如果你知道如何使用're';你馬上可以使用'regex'。 '將regex導入爲re'並且你有'\ p {}'語法支持。下面是一個[示例如何使用'\ p {P}']刪除字符串中的所有標點符號(http://stackoverflow.com/a/11066687) – jfs 2013-12-21 02:11:34

5

說到自制的解決方案的,前一段時間我寫了一個小program能夠做到這一點 - 轉換寫成\p{...}到值的範圍爲Unicode類別,該Unicode specification(v.5.0.0)提取。僅支持類別(例如:LZs),並且僅限於BMP。我在這裏發佈它,以防有人發現它有用(儘管Oniguruma真的看起來更好一些)。

用法示例:

>>> from unicode_hack import regex 
>>> pattern = regex(r'^\\p{Lu}(\\p{L}|\\p{N}|_)*') 
>>> print pattern.match(u'疂_1+2').group(0) 
疂_1 
>>> 

這裏的source。還有一個JavaScript version,使用相同的數據。

+1

不錯的一個,儘管您使用的是手工製作的文字在代碼中。這些文字是從規範的某些文本形式生成的,這將是很好的。或者從unicodedata(http://docs.python.org/library/unicodedata.html#module- unicodedata)。您可能可以運行所有有效的unicode代碼點並通過unicodedata.category()運行它們,並使用輸出來填充地圖... – ThomasH 2012-03-06 17:43:17

+0

感謝您的提示,我可能會在某一天實現這一點。上面的代碼首先是爲JavaScript創建的(當時沒有什麼明智的選擇),然後移植到Python。我在規格上運行了一些正則表達式,並用一次性腳本完成,但我同意一個可重複的過程本來會更好,所以我可以保持它最新的。 – mgibsonbr 2012-03-07 00:52:10

+0

我已經破解了一個動態構建地圖的快速函數(只有字符列表作爲值): def unicats(maxu): m = defaultdict(列表) 我在範圍內(maxu): 嘗試:cat = unicodedata.category(unichr(i)) 除外:cat =無 if cat:m [cat] .append(i) return m m = unicats(10FFFF) 請注意,某些類別會變得非常大(例如len(m ['Cn'])== 873882)。 – ThomasH 2012-03-07 09:09:56