組合語言(第3版,王爽著):實驗9 根據材料程式設計
1.非貪婪模式 - {x,y}?
非貪婪模式是指在使用正則匹配時,儘可能少的匹配(預設是貪婪模式,即:儘可能多的匹配)。例:
>>> re.search(r'[\d]{2,5}?','091234568')
<_sre.SRE_Match object; span=(0, 2), match='09'>
在這裡{2,5}?匹配只是匹配2-5個[\d]時只要滿足2(最少的)個就好,在看看貪婪模式:
>>> re.search(r'[\d]{2,5}','091234568')
<_sre.SRE_Match object; span=(0, 5), match='09123'>
這時候,匹配2-5個[\d]時,預設匹配最多的5個。
注意:貪婪和非貪婪模式的區別就是重複操作符後有沒有?字元
2.分組
正則表示式提供了一個機制將表示式分組,匹配的結果也將按照表達式單獨分組。例:
>>> m = re.search(r'(\d{3})-(\d{5})','029-25642')
>>> m.group()
'029-25642'
>>> m.groups()
('029', '25642')
>>> m.group(2)
'25642'
可以通過m.groups()看到分組匹配結果,通過m.group(index)檢視具體編號的分組結果(編號從1開始,0是完整的匹配)。那分組有什麼用呢,好像也沒什麼特殊的含義,不急,下面會用到。
3.引用分組(回溯) - \N
有這麼一種情況,比如假設我要找出一個html文字中的所有<a></a>標籤,怎麼辦?試試這樣:
>>> re.search(r'<(\w+)>.+</(\w+)>','<a>this is a demo</e>')
<_sre.SRE_Match object; span=(0, 21), match='<a>this is a demo</e>'>
奇怪的事情來了,為什麼<a></e>被匹配成功了,顯然結果並不是想要的,那怎麼才能只匹配<a></a>而過濾掉其他的呢(比如<a></e>)?答案就是引用分組,例:
Python客棧送紅包、紙質書
>>> re.search(r'<(\w+)>.+</\1>','<a>this is a demo</e><p>demo two</p>')
<_sre.SRE_Match object; span=(21, 36), match='<p>demo two</p>'>
這裡\1是關鍵,意思就是當前位置匹配的結果需要和第一個分組匹配的結果一致,或者說第一個分組的匹配結果期望在這裡再次出現。以此類推。該方法最多隻能匹配前99個分組。
4.分組命名 - (?P<name>.*)
分組命名最開始由python引入,比如Django路由中會用到。分組命名的好處是方便,直接使用名字比編號要簡單而且不會變化,例:
>>> m = re.search(r'(?P<first_name>\d{3})-(?P<second_name>\d{4})','029-8967')
>>> m.group('first_name')
'029'
>>> m.groupdict()
{'first_name': '029', 'second_name': '8967'}
當然,命名分組仍然是編號分組,依然可以使用編號進行查詢分組。
5.先行斷言 - X(?!Y)、X(?=Y)
假設有這麼一種情況,要查詢所有163信箱的文字,也就是@163.com結尾的所有email賬號資訊,也就是說不要@163.com這部分,但是其還要參與匹配。這就用到了先行斷言,也即基於之後的內容是否存在接收或拒絕一個匹配,而不需要接下來的內容作為匹配的一部分。例:
>>> re.search(r'h(?!e)','hello home!')
<_sre.SRE_Match object; span=(6, 7), match='h'>
h(?!e)表示匹配h,而且h後面不能是e,此處匹配成功的是home,但是隻返回h
>>> re.search(r'h(?=e)','hello home!')
<_sre.SRE_Match object; span=(0, 1), match='h'>
h(?=e)表示匹配he,此處匹配成功的是hello,但是隻返回h
6.標記
不區分大小寫:re.IGNORECASE(簡寫re.I)-使得正則表示式不區分大小寫
點匹配換行符:re.DOTALL(簡寫re.S)-使得 . 符號可以匹配換行符
多行模式:re.MULTILINE(簡寫re.M)-使得^$字元可以匹配任意行的開始與結束
詳細模式:re.VERBOSE(簡寫re.X)-使得正則表示式可以換行書寫,且可以加入註釋
除錯模式:re.DEBUG-將除錯資訊輸出到sys.stderr
使用多個標記時,使用|分隔,如re.S|re.M