1.元字符
①方括號 [ ]:指定一個字符類用於存放你需要匹配的字符集合
[abc] 會匹配字符 a,b 或 c;
[a-c] 可以實現相同的功能
[akm$] 會匹配任何字符 'a','k','m' 或 '$','$' 是一個元字符,但在方括號中它不表示特殊含義,它只匹配 '$'字符本身。
[^5] 會匹配除了 '5' 之外的任何字符
②反斜槓\:如果在反斜槓後邊緊跟着一個元字符,那麼元字符的“特殊功能”也不會被觸發
例如需要匹配符號 [ 或 \,可以在它們前面加上一個反斜槓,以消除它們的特殊功能:\[,\\。
反斜槓後邊跟一些字符還可以表示特殊的意義
其中d:digit,s:space,w:word
它們可以包含在一個字符類中,並且一樣擁有特殊含義。例如 [\s,.] 是一個字符類,它將匹配任何空白字符(/s 的特殊含義),',' 或 '.'。
爲避免反斜槓冗餘的情況,對於原字符串,需要在其前面加上r。
③ * :用於指定前一個字符匹配零次或者多次。
例如 ca*t 將匹配 ct(0 個字符 a),cat(1 個字符 a),caaat(3 個字符 a),等等。
注:正則匹配是貪婪的,在開始時儘可能匹配多的內容,再進行回退。
如 a[bcd]*b匹配abcbd,首先匹配到a,然後在匹配 [bcd]*這一部分時,由於是儘可能多的匹配,會直接匹配到字符串結尾,
再進一步匹配b時,發現不滿足,就會回退字符串再次嘗試匹配b,這裏就是回退到d,匹配不成又回退到b,匹配成功,返回結果。
④ + :用於指定前一個字符匹配一次或者多次。
要特別注意 * 和 + 的區別:* 匹配的是零次或者多次,所以被重複的內容可能壓根兒不會出現;+ 至少需要出現一次。例如 ca+t 會匹配 cat 和 caaat,但不會匹配 ct。
⑤ ? :用於指定前一個字符匹配零次或者一次。
⑥ {m,n} :它的含義是前一個字符必須匹配 m 次到 n 次之間。
{,n} 相當於 {0,n};如果是 {m,} 相當於 {m,+無窮};如果是 {n},則是重複前一個字符 n 次。
⑦ | :
或操作符,對兩個正則表達式進行或操作。如果 A 和 B 是正則表達式,A | B 會匹配 A 或 B 中出現的任何字符。爲了能夠更加合理的工作,| 的優先級非常低。例如 Fish|C 應該匹配 Fish 或 C,而不是匹配 Fis,然後一個 'h' 或 'C'。
⑧ ^ :
匹配字符串的起始位置。如果設置了 MULTILINE 標誌,就會變成匹配每一行的起始位置。在 MULTILINE 中,每當遇到換行符就會立刻進行匹配。
re.search('^From', 'From Here to Eternity')
#結果:<_sre.SRE_Match object; span=(0, 4), match='From'>
re.search('^From', 'Reciting From Memory')
#結果:None
⑨ $ :匹配字符串的結束位置,每當遇到換行符也會離開進行匹配。
⑩ \A,\Z:
只匹配字符串的起始位置。如果沒有設置 MULTILINE 標誌的時候(即re.M),\A 和 ^ 的功能是一樣的;但如果設置了 MULTILINE 標誌,則會有一些不同:\A 還是匹配字符串的起始位置,但 ^ 會對字符串中的每一行都進行匹配。
⑪\b:單詞邊界,這是一個只匹配單詞的開始和結尾的零寬斷言。“單詞”定義爲一個字母數字的序列,所以單詞的結束指的是空格或者非字母數字的字符。
- >>> p = re.compile(r'\bclass\b')
- >>> print(p.search('no class at all'))
- <_sre.SRE_Match object; span=(3, 8), match='class'>
- >>> print(p.search('the declassified algorithm'))
- None
- >>> print(p.search('one subclass is'))
- None
⑫ ():分組符
- >> p = re.compile('(a(b)c)d')
- >>> m = p.match('abcd')
- >>> m.group(0)
- 'abcd'
- >>> m.group(1)
- 'abc'
- >>> m.group(2)
- 'b'
- >>> m.groups()
- ('abc', 'b')
⑬ \1,\2...:
\1 表示引用前邊成功匹配的序號爲 1 的子組。
- >>> p = re.compile(r'(\b\w+)\s+\1')
- >>> p.search('Paris in the the spring').group()
- 'the the'
2.方法
注意,由於方法可能會因無結果,後續使用group時可配合try使用,也可以利用if判斷是否有匹配對象返回。
使用過程:先進行compile編譯,再利用編譯後的變量調用函數。
如:
p = re.compile('[a-z]+')
result = p.match("aaa")
結果:
<_sre.SRE_Match object; span=(0, 5), match='aaa'>
返回的是一個匹配對象,而匹配對象還有對應的方法。
如果不使用編譯模式,也可以直接使用re的全局函數,如re.match(r'\s+', 'aa aa'),即第一個爲正則字符串,第二個爲匹配的字符串,當然,這種速度相對較慢。
3.匹配對象
4.re.
①re.X
這個選項忽略規則表達式中的空白和註釋,並允許使用 ’#’ 來引導一個註釋。這樣可以讓你把規則寫得更美觀些。
rc = re.compile(r"""
# start a rule
/d+
# number
|
[a-zA-Z]+
# word
""", re.X)
res = rc.match('aaaa')
# print(res)
print(res.group())
②re.I
忽略大小寫
③re.S
使得 . 可以匹配任何字符,包括換行符。如果不使用這個標誌,. 將匹配除了換行符的所有字符。
a = """sdfkhellolsdlfsdfiooefo:
877898989worldafdsf"""
b = re.findall('hello(.*?)world',a)
c = re.findall('hello(.*?)world',a,re.S)
print ('b is ' , b)
print ('c is ' , c)
# 輸出結果:
# b is []
# c is ['lsdlfsdfiooefo:\n877898989']
④re.A
使得 \w,\W,\b,\B,\s 和 \S 只匹配 ASCII 字符,而不匹配完整的 Unicode 字符。這個標誌僅對 Unicode 模式有意義,並忽略字節模式。
⑤re.L
LOCALE
使得 \w,\W,\b 和 \B 依賴當前的語言(區域)環境,而不是 Unicode 數據庫。
區域設置是 C 語言的一個功能,主要作用是消除不同語言之間的差異。例如你正在處理的是法文文本,你想使用 \w+ 來匹配單詞,但是 \w 只是匹配 [A-Za-z] 中的單詞,並不會匹配 'é' 或 'ç'。如果你的系統正確的設置了法語區域環境,那麼 C 語言的函數就會告訴程序 'é' 或 'ç' 也應該被認爲是一個字符。當編譯正則表達式的時候設置了 LOCALE 的標誌,\w+ 就可以識別法文了,但速度多少會受到影響。
⑥re.M
通常 ^ 只匹配字符串的開頭,而 $ 則匹配字符串的結尾。當這個標誌被設置的時候,^ 不僅匹配字符串的開頭,還匹配每一行的行首;& 不僅匹配字符串的結尾,還匹配每一行的行尾。
5.group與groups
m = re.search(r"([0-9])*", "123")
print(m.groups())
# 結果:('3',) 原因:[0-9]是一個字符,由於貪婪匹配,會盡可能匹配到最後的3
m = re.search(r"([0-9])*", "123")
print(m.group())
# 結果:123 返回整個匹配的字符串而非括號內的分組
6.非捕獲組和命名組
①非捕獲組
有時候只是需要用一個組來表示部分正則表達式,並不需要這個組去匹配任何東西,這時可以通過非捕獲組來明確表示意圖。非捕獲組的語法是 (?:...),這個 ... 你可以替換爲任何正則表達式。
m = re.search(r"1(?:[abc])+1", "1abc1") #注意養成良好的加r習慣
print(m.group())
②命名組
命名組的語法是 Python 特有的擴展語法:(?P<name>)。很明顯,< > 裏邊的 name 就是命名組的名字啦。命名組除了有一個名字標識之外,跟其他捕獲組是一樣的。
匹配對象的所有方法不僅可以處理那些由數字引用的捕獲組,還可以處理通過字符串引用的命名組。除了使用名字訪問,命名組仍然可以使用數字序號進行訪問:
- >>> p = re.compile(r'(?P<word>\b\w+\b)')
- >>> m = p.search( '(((( Lots of punctuation )))' )
- >>> m.group('word')
- 'Lots'
- >>> m.group(1)
- 'Lots'
7.擴展機制
①前向斷言(?=...)
前向肯定斷言。如果當前包含的正則表達式(這裏以 ... 表示)在當前位置成功匹配,則代表成功,否則失敗。一旦該部分正則表達式被匹配引擎嘗試過,就不會繼續進行匹配了;剩下的模式在此斷言開始的地方繼續嘗試。
②前向否定斷言(?!...)
前向否定斷言。這跟前向肯定斷言相反(不匹配則表示成功,匹配表示失敗)。
例如想匹配擴展名不是 bat 的文件,使用.*[.](?!bat$).*$即可
如果正則表達式 bat 在當前位置不匹配,嘗試剩下的部分正則表達式;如果 bat 匹配成功,整個正則表達式將會失敗(因爲是前向否定斷言嘛^_^)。(?!bat$) 末尾的 $ 是爲了確保可以正常匹配像 sample.batch 這種以 bat 開始的擴展名。
同樣,有了前向否定斷言,要同時排除 bat 和 exe 擴展名,也變得相當容易:
.*[.](?!bat$|exe$).*$