2010-01-10 165 views
25

如何匹配字母字符與正則表達式。我想要一個\w但不在\d中的字符。我想它與unicode兼容,這就是爲什麼我不能使用[a-zA-Z]python-re:如何匹配字母字符

+1

「兼容Unicode」 - 這是否意味着要E和匹配é,例如? – Seth 2010-01-10 23:46:09

+0

在Python中,記住要指明一個unicode字符串,你必須使用這個:'u'Unicode string here'' - 假設你嘗試了str.find(),其中str是你的unicode字符串? – Alex 2010-01-11 00:11:24

+3

我的意思是我想匹配一個,é,あ,日但不是1,。 (點),9,9等。例如, 。 – basaundi 2010-01-11 08:23:41

回答

42

你的前兩句相互矛盾。 「在\w但不在\d」中包含下劃線。我從你的第三句話假設你不想強調。

在信封背面使用維恩圖有助於。讓我們來看看,我們不想要的東西:

(1)不受\w匹配(即不希望任何非字母,數字和下劃線)字符=>\W
(2)位數= >\d
(3)下劃線=>_

所以我們不想要的東西是在字符類[\W\d_]任何東西,因此我們做什麼要的是在字符類[^\W\d_]

這裏什麼是一個簡單的例子(Python 2.6)。

>>> import re 
>>> rx = re.compile("[^\W\d_]+", re.UNICODE) 
>>> rx.findall(u"abc_def,k9") 
[u'abc', u'def', u'k'] 

進一步探索揭示了這種方法的一些怪癖:

>>> import unicodedata as ucd 
>>> allsorts =u"\u0473\u0660\u06c9\u24e8\u4e0a\u3020\u3021" 
>>> for x in allsorts: 
...  print repr(x), ucd.category(x), ucd.name(x) 
... 
u'\u0473' Ll CYRILLIC SMALL LETTER FITA 
u'\u0660' Nd ARABIC-INDIC DIGIT ZERO 
u'\u06c9' Lo ARABIC LETTER KIRGHIZ YU 
u'\u24e8' So CIRCLED LATIN SMALL LETTER Y 
u'\u4e0a' Lo CJK UNIFIED IDEOGRAPH-4E0A 
u'\u3020' So POSTAL MARK FACE 
u'\u3021' Nl HANGZHOU NUMERAL ONE 
>>> rx.findall(allsorts) 
[u'\u0473', u'\u06c9', u'\u4e0a', u'\u3021'] 

U + 3021(杭州數字一)被視爲數字(因此它匹配\ W),但它似乎Python的解釋「數字」表示‘十進制數字’(類別釹),所以它不匹配\ d

U + 2438(帶圈拉丁小寫字母Y)不匹配\ W

所有的中日韓表意文字被歸類作爲「字母」並因此匹配\ w

以上3點中的任何一點是否值得關注,該方法是最好的,您將從當前發佈的re模塊中獲得最佳效果。類似\ p {letter}的語法將來會出現。

+0

謝謝! 儘管你提到的怪癖,我想我可以從這裏開始,看看我可以調整。 – basaundi 2010-01-11 08:18:50

2

什麼:

\p{L} 

您可以使用此文件作爲參考:Unicode Regular Expressions

編輯:似乎Python doesn't handle Unicode expressions。看看這個鏈接:Handling Accented Characters with Python Regular Expressions -- [A-Z] just isn't good enough(不再有效時,鏈接到互聯網檔案館)

另一個引用:


對於後代,這裏是博客上的例子:

import re 
string = 'riché' 
print string 
riché 

richre = re.compile('([A-z]+)') 
match = richre.match(string) 
print match.groups() 
('rich',) 

richre = re.compile('(\w+)',re.LOCALE) 
match = richre.match(string) 
print match.groups() 
('rich',) 

richre = re.compile('([é\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

richre = re.compile('([\xe9\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

richre = re.compile('([\xe9-\xf8\w]+)') 
match = richre.match(string) 
print match.groups() 
('rich\xe9',) 

string = 'richéñ' 
match = richre.match(string) 
print match.groups() 
('rich\xe9\xf1',) 

richre = re.compile('([\u00E9-\u00F8\w]+)') 
print match.groups() 
('rich\xe9\xf1',) 

matched = match.group(1) 
print matched 
richéñ 
+1

謝謝,但我無法知道一個字符是(CJK)標點符號還是0-9以外的數字符號,如果我執行一個範圍像\ u00E9- \ u00F8。 – basaundi 2010-01-10 23:55:42

+1

你可以使用字母範圍,如果你引用一個像http://www.tamasoft.co.jp/en/general-info/unicode.html這樣的文檔,並選擇所有的字母間隔(這可能是無聊的... ... );這個鏈接也可以幫助你:http://kourge.net/projects/regexp-unicode-block – 2010-01-11 00:03:53

+0

這個實例的例子在這裏會有所幫助。 – 2014-06-15 06:20:57

0

您可以使用下列表達式之一匹配的單個字母:

(?![\d_])\w 

\w(?<![\d_]) 

在這裏,我匹配\w,但檢查[\d_]之前不匹配/後。

從文檔:

(?!...) 
Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'. 

(?<!...) 
Matches if the current position in the string is not preceded by a match for .... This is called a negative lookbehind assertion. Similar to positive lookbehind assertions, the contained pattern must only match strings of some fixed length and shouldn’t contain group references. Patterns which start with negative lookbehind assertions may match at the beginning of the string being searched.