1. 分割字串-使用多個界定符【re.split()】
>>> line = 'asdf fjdk; afed, fjek,asdf, foo' >>> import re >>> re.split(r'[;,\s]\s*', line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
string
物件的 split()
方法只適應於非常簡單的字串分割情形, 它並不允許有多個分隔符或者是分隔符周圍不確定的空格。 當你需要更加靈活的切割字串的時候,最好使用 re.split()
方法
>>> fields = re.split(r'(;|,|\s)\s*', line) >>> fields ['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo'] >>>
如果re.split()中使用了括號捕捉分組。如果使用了括號,那麼被匹配的文字也將出現在結果列表中。
如果不想保留分割字串到結果列表中去,但仍然需要使用到括號來分組正規表示式的話, 確保你的分組是非捕獲分組,形如 (?:...)
。比如
>>> re.split(r'(?:,|;|\s)\s*', line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo'] >>>
2. 字串的開頭匹配或結尾匹配【str.startwith()或 str.endwith()】
如果想匹配多種可能時.只需將所有的匹配項放入到一個元組【tuple】中然後傳給str.startwith()或 str.endwith()中
>>> filenames [ 'Makefile', 'foo.c', 'bar.py', 'spam.c', 'spam.h' ] >>> [name for name in filenames if name.endswith(('.c', '.h')) ] ['foo.c', 'spam.c', 'spam.h']
3. 用Shell萬用字元匹配字串--【fnmath模組提供的兩個函式--fnmatch()和fnmatchcase()】
Unix Shell 中常用的萬用字元(比如 *.py
, Dat[0-9]*.csv
等)去匹配文字字串
# Shell萬用字元 # # ? 任意單個字元 # * 任意0個或多個字元 # [ ] 匹配方括號中的任意一個字元,如[abc] 則匹配abc中的一個 # [ - ] "-"代表範圍,例如:[a-z] 則匹配任意一個小寫字母; [0-9] 則匹配任意一個0-9之間的資料,但是注意[0-10]不可以,不能超過9 # [^] 邏輯非. 例如: [^0-9]匹配任意一個非數字字元
>>> from fnmatch import fnmatch, fnmatchcase >>> fnmatch('foo.txt', '*.txt') True >>> fnmatch('foo.txt', '?oo.txt') True >>> fnmatch('Dat45.csv', 'Dat[0-9]*') True >>> names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py'] >>> [name for name in names if fnmatch(name, 'Dat*.csv')] ['Dat1.csv', 'Dat2.csv']
fnmatch()
函式使用底層作業系統的大小寫敏感規則(不同的系統是不一樣的)來匹配模式。比如:
>>> # On OS X (Mac) >>> fnmatch('foo.txt', '*.TXT') False >>> # On Windows >>> fnmatch('foo.txt', '*.TXT') True >>>
如果你對這個區別很在意,可以使用 fnmatchcase()
來代替。它完全使用你的模式大小寫匹配。
常用場景:在處理非檔名的字串時候它們也是很有用的。檔名的匹配,最好使用 glob
模組
addresses = [ '5412 N CLARK ST', '1060 W ADDISON ST', '1039 W GRANVILLE AVE', '2122 N CLARK ST', '4802 N BROADWAY', ] 你可以像這樣寫列表推導: >>> from fnmatch import fnmatchcase >>> [addr for addr in addresses if fnmatchcase(addr, '* ST')] ['5412 N CLARK ST', '1060 W ADDISON ST', '2122 N CLARK ST'] >>> [addr for addr in addresses if fnmatchcase(addr, '54[0-9][0-9] *CLARK*')] ['5412 N CLARK ST'] >>>
4. 字串匹配和搜尋
如果你想匹配的是字面字串,那麼你通常只需要呼叫基本字串方法就行, 比如 str.find()
, str.endswith()
, str.startswith()
或者類似的方法:
re
模組。 為了解釋正規表示式的基本原理,假設你想匹配數字格式的日期字串比如 11/27/2012
,你可以這樣做>>> text1 = '11/27/2012' >>> text2 = 'Nov 27, 2012' >>> >>> import re >>> # Simple matching: \d+ means match one or more digits >>> if re.match(r'\d+/\d+/\d+', text1): ... print('yes') ... else: ... print('no') ... yes >>> if re.match(r'\d+/\d+/\d+', text2): ... print('yes') ... else: ... print('no') ... no >>>
如果你想使用同一個模式去做多次匹配,你應該先將模式字串預編譯為模式物件。比如:
>>> datepat = re.compile(r'\d+/\d+/\d+') >>> if datepat.match(text1): ... print('yes') ... else: ... print('no') ... yes >>> if datepat.match(text2): ... print('yes') ... else: ... print('no') ... no >>>
match()
總是從字串開始去匹配,如果你想查詢字串任意部分的模式出現位置, 使用 findall()
方法去代替。比如:
>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.' >>> datepat.findall(text) ['11/27/2012', '3/13/2013'] >>>
在定義正則式的時候,通常會利用括號去捕獲分組。
#在定義正則式的時候,通常會利用括號去捕獲分組 #捕獲分組可以使得後面的處理更加簡單,因為可以分別將每個組的內容提取出來 >>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)') >>> m = datepat.match('11/27/2012') >>> m <_sre.SRE_Match object at 0x1005d2750> >>> # Extract the contents of each group >>> m.group(0) '11/27/2012' >>> m.group(1) '11' >>> m.group(2) '27' >>> m.group(3) '2012' >>> m.groups() ('11', '27', '2012') >>> month, day, year = m.groups() >>> >>> # Find all matches (notice splitting into tuples) >>> text 'Today is 11/27/2012. PyCon starts 3/13/2013.' >>> datepat.findall(text) [('11', '27', '2012'), ('3', '13', '2013')] >>> for month, day, year in datepat.findall(text): ... print('{}-{}-{}'.format(year, month, day)) ... 2012-11-27 2013-3-13 >>>
正規表示式步驟: re.compile()編譯正規表示式字串, 然後使用match(), findall(), finditer()等方法
如果你想精確匹配,確保你的正規表示式以$結尾,就像這麼這樣:
>>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)$') >>> datepat.match('11/27/2012abcdef') >>> datepat.match('11/27/2012') <_sre.SRE_Match object at 0x1005d2750> >>>
最後,如果你僅僅是做一次簡單的文字匹配/搜尋操作的話,可以略過編譯部分,直接使用 re
模組級別的函式。比如:
>>> re.findall(r'(\d+)/(\d+)/(\d+)', text) [('11', '27', '2012'), ('3', '13', '2013')] >>>
2.5 字串搜尋和替換
對於簡單的字面模式,直接使用 str.replace()
方法即可,比如:str.replace('tihuan_qian', 'tihuan_hou')
複雜的模式,使用re模組的sub()函式。
例: 11/27/2012
的日期字串改成 2012-11-27
>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.' >>> import re >>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text) 'Today is 2012-11-27. PyCon starts 2013-3-13.' >>>
sub()
函式中的第一個引數是被匹配的模式,第二個引數是替換模式。反斜槓數字比如 \3
指向前面模式的捕獲組號。
>>> import re >>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)') >>> datepat.sub(r'\3-\1-\2', text) 'Today is 2012-11-27. PyCon starts 2013-3-13.'
result, n = re.subn(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
re.subn()可以知道替換次數