python學習--正則表達式
- 2020 年 1 月 13 日
- 筆記
正則表達式是一種用來匹配字元串的強有力的工具它的設計思想是用一種描述性的語言來給字元串定義一個規則,凡是符合規則的字元串,我們就認為它「匹配」了,否則,該字元串就是不合法的。
Python支援的正則表達式元字元和語法:
語法 | 說明 | 實例 | 完整匹配的字元串 |
|---|---|---|---|
一般字元 | 匹配自身 | a1b2c3 | a1b2c3 |
. | 匹配任意除換行符'n'外的字元 | l.l | lol|lpl|lfl |
轉義字元,使後一個字元改變原來的意思 | l.ll\l | l.lll | |
[...] | 對應的位置可以是字符集中任意字元,字符集中的字元可以逐個列出,也可以給出範圍如[abc]或[a-c],第一個字元如果是^則表示取反如[^abc]表示除abc以外的其他字元;所有特殊字元在字符集中都是去其原有特殊意義 | a[bcd]e | abeaceade |
d | 數字:[0-9] | adc | a2c |
D | 非數字:[^d] | aDc | axc |
s | 空白字元:[空格,trnfv] | asc | a c |
S | 非空白字元:[^s] | ||
w | 單詞字元:[_a-zA-Z0-9] | awc | axc |
W | 非單詞字元:[^w] | aWc | a c |
|---|---|---|---|
* | 匹配前一個字元0或無限次 | abc* | ababcccccc |
+ | 匹配前一個字元1或無限次 | abc+ | abcabcccccc |
? | 匹配前一個字元0或1次 | abc? | ababc |
{m} | 匹配前一個字元m次 | ab{2}c | abbc |
{m,n} | 匹配前一個字元m至n次;若省略m,匹配0至n次;若省略n,匹配m至無限次 | ab{1,2}c | abcabbc |
*? +? ??{m,n}? | 使* + ? {m,n}變成非貪婪模式 | ||
^ | 匹配字元串開頭在多行模式中匹配每一行的開頭 | ^abc | abc |
$ | 匹配字元串末尾在多行模式中匹配每一行的末尾 | abc$ | abc |
A | 僅匹配字元串開頭 | Aabc | abc |
Z | 僅匹配字元串末尾 | abcZ | abc |
|---|---|---|---|
b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'erb' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 | ||
B | 匹配非單詞邊界。'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 | ||
| | 左右表達式任意匹配一個總是先嘗試匹配左邊表達式,一旦匹配成功則跳過匹配右邊的表達式 | abc|def | abcdef |
(...) | 被括起來的表達式作為分組 | (abc){2}ab(12|45)c | abcabcab45c |
(?#...) | #後的內容作為注釋被忽略 | ab(?#com..)123 | ab123 |
反斜杠
與大多數程式語言相同,正則表達式里使用""作為轉義字元,這就可能造成反斜杠困擾。假如你需要匹配文本中的字元"",那麼使用程式語言表示的正則表達式里將需要4個反斜杠"\\":前兩個和後兩個分別用於在程式語言里轉義成反斜杠,轉換成兩個反斜杠後再在正則表達式里轉義成一個反斜杠。Python里的原生字元串很好地解決了這個問題,這個例子中的正則表達式可以使用r"\"表示。同樣,匹配一個數字的"\d"可以寫成r"d"。有了原生字元串,你再也不用擔心是不是漏寫了反斜杠,寫出來的表達式也更直觀。
看一個例子:d{3}s+d{3,8}
我們來從左到右解讀一下:
d{3}表示匹配3個數字,例如'010';
s可以匹配一個空格(也包括Tab等空白符),所以s+表示至少有一個空格,例如匹配' ',' '等;
d{3,8}表示3-8個數字,例如'1234567'。
綜合起來,上面的正則表達式可以匹配以任意個空格隔開的帶區號的電話號碼。
如果要匹配'010-12345'這樣的號碼呢?由於'-'是特殊字元,在正則表達式中,要用''轉義,所以,上面的正則是d{3}-d{3,8}。
進階
要做更精確地匹配,可以用[]表示範圍,比如:
[0-9a-zA-Z_]可以匹配一個數字、字母或者下劃線;
[0-9a-zA-Z_]+可以匹配至少由一個數字、字母或者下劃線組成的字元串,比如'a100','0_Z','Py3000'等等;
[a-zA-Z_][0-9a-zA-Z_]*可以匹配由字母或下劃線開頭,後接任意個由一個數字、字母或者下劃線組成的字元串,也就是Python合法的變數;
[a-zA-Z_][0-9a-zA-Z_]{0, 19}更精確地限制了變數的長度是1-20個字元(前面1個字元+後面最多19個字元)。
A|B可以匹配A或B,所以[P|p]ython可以匹配'Python'或者'python'。
^表示行的開頭,^d表示必須以數字開頭。
$表示行的結束,d$表示必須以數字結束。
你可能注意到了,py也可以匹配'python',但是加上^py$就變成了整行匹配,就只能匹配'py'了。
re模組
re 模組使 Python 語言擁有全部的正則表達式功能。
re.match
re.match 嘗試從字元串的開始匹配一個模式。
語法:
re.match(pattern, string, flags=0)
參數說明:
pattern 匹配的正則表達式
string 要匹配的字元串。
flags 標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等。
匹配成功re.match方法返回一個匹配的對象,否則返回None。
eg:
import re sss = re.match(r'^d{3}-d{3,8}$', '010-12345') print(sss) <_sre.SRE_Match object; span=(0, 9), match='010-12345'>可以使用group(num) 或 groups() 匹配對象函數來獲取匹配表達式。
group(num=0) 匹配的整個表達式的字元串,group() 可以一次輸入多個組號,在這種情況下它將返回一個包含那些組所對應值的元組。
groups() 返回一個包含所有小組字元串的元組,從 1 到 所含的小組號。
eg:
line = "Cats are smarter than dogs" matchObj = re.match(r'(.*) are (.*?) .*', line) if matchObj: print("matchObj.group() : ", matchObj.group()) print("matchObj.groups() : ", matchObj.groups()) print("matchObj.group(1) : ", matchObj.group(1)) print("matchObj.group(2) : ", matchObj.group(2)) else: print("No match!!") matchObj.group() : Cats are smarter than dogs matchObj.groups() : ('Cats', 'smarter') matchObj.group(1) : Cats matchObj.group(2) : smarterre.search
語法:
re.search(pattern, string, flags=0)
re.match只匹配字元串的開始,如果字元串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字元串,直到找到一個匹配。
eg:
import re line = "Cats are smarter than dogs" matchObj = re.match(r'are', line) if matchObj: print("are ", matchObj.group()) else: print("No match!!") matchObj = re.search(r'are', line) if matchObj: print("are : ", matchObj.group()) else: print("No match!!") No match!! are : are切分字元串
語法:
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能夠匹配的子串將string分割後返回列表。maxsplit用於指定最大分割次數,不指定將全部分割。
a = re.split(r'd+', 'one1two2three3four') print(a) ['one', 'two', 'three', 'four'] s = re.split(r's+', 'a b c d w') print(s) d = re.split(r'[s,;]+', 'a ,a;b,v g,d , ;') print(d) ['a', 'b', 'c', 'd', 'w'] ['a', 'a', 'b', 'v', 'g', 'd', '']
findall
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
搜索string,以列表形式返回全部能匹配的子串。
u = re.findall(r'd', 'one1two2three3four4') print(u) ['1', '2', '3', '4']
finditer
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags])
搜索string,返回一個順序訪問每一個匹配結果(Match對象)的迭代器。
u = re.finditer(r'd', 'one1two2three3four4') for i in u: print(i.group()) 1 2 3 4
re.sub用於替換字元串中的匹配項。
語法:
re.sub(pattern, repl, string, max=0)
返回的字元串是在字元串中用 RE 最左邊不重複的匹配來替換。如果模式沒有發現,字元將被沒有改變地返回。
可選參數 count 是模式匹配後替換的最大次數;count 必須是非負整數。預設值是 0 表示替換所有的匹配
#!/usr/bin/python import re phone = "2004-959-559 # This is Phone Number" num = re.sub(r'#.*', "", phone) print(num) nun = re.sub(r'D', "", num) print(nun) 2004-959-559 2004959559
正則表達式非常強大,要講清楚正則的所有內容,可以寫一本厚厚的書了。如果你經常遇到正則表達式的問題,你可能需要一本正則表達式的參考書。