1拌喉、前言
正則表達式俐银,如果有一定編程經(jīng)驗的同學尿背,一定知道,可能你知道捶惜,但又說不出個所以然來田藐,平時不經(jīng)常使用,很容易就忘記吱七,有一部分原因汽久,我認為是總結(jié)的內(nèi)容,不夠簡單和深刻踊餐。所以景醇,自己嘗試總結(jié)一下正則表達式的基礎(chǔ)知識點,對于大部分的編程場景應(yīng)該足夠使用啦市袖。另外啡直,也希望通過總結(jié),以便后續(xù)忘記時苍碟,能快速的記憶起來酒觅,這就是本文章的主要內(nèi)容。
2微峰、正則表達式
匹配字符集
語法 | 匹配 | 示例 |
---|---|---|
. |
匹配任意字符(除了\n ) |
表達式:. 匹配任意一個字符 |
[...] |
匹配字符集(... 表示任意字符) |
表達式:[a-zA-Z] 匹配任意一個小寫或大寫的字母舷丹。表達式: [iHTC] 匹配 "i", "H", "T" 和 "C"。表達式: [e-k] 匹配 "e" 到 "k" 之間的字符蜓肆。 |
\d |
匹配數(shù)字 | 表達式:a\d 颜凯,匹配字符串 "aaa123" 中的 a1 谋币。表達式: a.\d ,匹配字符串 "aaa123" 中的 aa1 症概。 |
\D |
匹配非數(shù)字 | 表達式:a.\D 蕾额,匹配字符串 "aaa123" 中的 aaa 。 |
\s |
匹配空白字符(包括空格彼城、制表符诅蝶、換頁符等空白字符,[ \t\n\r\f] ) |
表達式:a.\s 募壕,匹配字符串 "aaa 123" 中的 aa (最后是空格) 调炬。 |
\S |
匹配非空白字符 | 表達式:a.\S ,匹配字符串 "aaa 123" 中的 aaa 舱馅。 |
\w |
匹配單詞字符([a-zA-Z0-9_]和漢字) | 表達式:a.\w ,匹配字符串 "aaa 123" 中的 aaa 棘钞。 |
\W |
匹配非單詞字符 | 表達式:a.\W 资溃,匹配字符串 "aaa 123" 中的 aa (最后是空格) 。 |
\ |
轉(zhuǎn)義字符 |
\r , \n 代表回車和換行符; \t 制表符; \\ 代表 "" 本身; \^ 匹配 ^ 符號本身; \$ 匹配 $ 符號本身; \. 匹配小數(shù)點(.)本身宝恶。 |
匹配量詞(Quantifier)
語法 | 匹配 | 示例 |
---|---|---|
* |
匹配表達式出現(xiàn) 0次或者無限次垫毙,相當于 {0,} | 表達式:a* 拱绑,匹配字符串 "aaa123" 中的 aaa 。 |
+ |
匹配表達式至少出現(xiàn) 1次或者無限次膀藐,相當于 {1,} | 表達式:a+ 额各,匹配字符串 "aaa123" 中的 aaa 吧恃。 |
? |
匹配表達式 0次或者 1次,相當于 {0,1} | 表達式:a? 傲醉,匹配字符串 "aaa123" 中的 a 硬毕。 |
{m,n} |
匹配表達式至少重復 m 次,最多重復 n 次 | 表達式:a{1,2} 苞七,匹配字符串 "aaa123" 中的 aa 挪丢。 |
{m} |
匹配表達式重復 m 次 | 表達式:a{3} 乾蓬,匹配字符串 "aaa123" 中的 aaa 任内。 |
{m,} |
匹配表達式至少重復 m 次 | 表達式:a{1,} 融柬,匹配字符串 "aaa123" 中的 aaa 。 |
*? |
匹配模式變?yōu)榉秦澙罚ūM可能少匹配字符)越除,匹配表達式可以為 0次摘盆,也可以是無限次 | 表達式:a[0-9]*?23' ,匹配字符串 "aaa123" 中的 a123 饱苟。如果匹配字符串 "aaa23" 則為 a23 。 如果匹配字符串 "aaa456123" 則為 a456123 类垦。 |
+? |
匹配模式變?yōu)榉秦澙罚ūM可能少匹配字符)蚤认,匹配表達式至少 1次酿傍,也可以是無限次 | 表達式:a[0-9]+?23 ,匹配字符串 "aaa123" 中的 a123 氯析。如果匹配字符串 "aaa23" 則匹配失敗 掩缓。 如果匹配字符串 "aaa456123" 則為 a456123 。 |
?? |
匹配模式變?yōu)榉秦澙罚ūM可能少匹配字符)巡通,匹配表達式最多 1次宴凉,也可以是 0次 | 表達式:a[0-9]??23 表悬,匹配字符串 "aaa123" 中的 a123 。如果匹配字符串 "aaa23" 則為 a23 籽暇。 如果匹配字符串 "aaa456123" 則匹配失敗戒悠。 |
{m,n}? |
非貪婪模式舟山,匹配符合的最短的字符串 | 表達式:a[0-9]{1,4}?23 ,匹配字符串 "aaa123" 中的 a123 六孵。如果匹配字符串 "aaa23" 則匹配失敗 幅骄。 如果匹配字符串 "aaa456123" 則為 a456123 |
匹配邊界
語法 | 匹配 | 示例 |
---|---|---|
^ |
匹配字符串開頭 | 表達式:^\d 表示必須以數(shù)字開頭拆座。表達式: [^abc] 匹配 a , b , c 之外的任意一個字符。 |
$ |
匹配字符串結(jié)尾 | 表達式:*.com$ 匹配 .com 結(jié)尾的字符串孕索。\d$ 表示必須以數(shù)字結(jié)束搞旭。 |
\A |
指定的字符串匹必須出現(xiàn)在開頭 | 表達式:\Aa ,匹配字符串 "aaa123" 中的 a 镇眷。 |
\Z |
指定的字符串匹必須出現(xiàn)在結(jié)尾欠动。如果是存在換行惑申,只匹配到換行前的結(jié)束字符串。 | 表達式:\d\Z 人芽,匹配字符串 "aaa123" 中的 3 碗脊。 |
\b |
匹配一個單詞邊界,但只在單詞開始或結(jié)尾的位置衙伶,即匹配 \w 和 \W 之間害碾。(本身不匹配任何字符) |
表達式:\b4 慌随,匹配字符串 "aaa123 456" 中的 4 。表達式: \b5 丸逸,匹配字符串 "aaa123 456" 則為失敗黄刚。 |
\B |
匹配非單詞邊界民效,但不能在詞的開頭或者結(jié)尾,即匹配 [^\b] 业扒。(本身不匹配任何字符) |
表達式:\B4 程储,匹配字符串 "aaa123 456" 則為失敗。表達式: \B5 摊灭,匹配字符串 "aaa123 456" 中的 5 咏窿。 |
匹配條件分組
語法 | 匹配 | 示例 |
---|---|---|
| |
匹配左右任意一個表達式 | 表達式:a|b ,匹配字符串 "aaa123" 中的 a 集嵌。 |
(ab) |
括號中表達式作為一個分組 | 表達式:(a1) ,匹配字符串 "aaa123" 中的 a1 怜珍。表達式: (P|p)ython 酥泛,可以匹配 Python 或者 python嫌拣。 |
(?:exp) |
表示非捕獲分組,匹配 pattern 但不獲取匹配結(jié)果捶索。 | 表達式:([a-z]*)([0-9]*)([a-z]*) 腥例,匹配字符串 "aaa123def456" 中的 'aaa', '123', 'def' 酝润。表達式: (?:[a-z]*)([0-9]*)([a-z]*) ,匹配字符串 "aaa123def456" 中的 '123', 'def' 构回。 |
\<number> |
引用編號為 number 的分組(規(guī)則)匹配到的字符串 | 表達式:(\d)def\1 捐凭,匹配字符串 "aaa123def321" 中的 3def3 茁肠。 |
(?P<name>) |
給分組起一個別名 name | 表達式:(?P<tag>\d)def(?P=tag) ,匹配字符串 "aaa123def321" 中的 3def3 垦梆。 |
(?P=name) |
引用別名為 name 的分組匹配字符串 | 表達式:<(?P<tag>\w*)>.*</(?P=tag)> ,匹配字符串 <html><h1>www.iHTCboy.com</h1><html> 中的 <h1>www.iHTCboy.com</h1> 印蓖。 |
預搜索
語法 | 匹配 | 示例 |
---|---|---|
(?=exp) |
斷言自身出現(xiàn)的位置的后面能匹配表達式 exp赦肃,exp1(?=exp2):查找 exp2 前面的 exp1公浪。 | 表達式:Windows(?=XP|7|8) 能匹配Windows7 中的 “Windows”欠气,但不能匹配 Windows10 中的“Windows”。 |
(?!exp) |
斷言自身出現(xiàn)的位置的后面不能匹配表達式 exp队塘,exp1(?!exp2):查找后面不是 exp2 的 exp1憔古。 | 表達式:Windows(?!XP|7|8) 能匹配Windows10 中的“Windows”淋袖,但不能匹配 Windows7 中的“Windows”适贸。 |
(?<=exp) |
斷言自身出現(xiàn)的位置的前面能匹配表達式 exp涝桅,(?<=exp2)exp1:查找 exp2 后面的 exp1冯遂。 | 表達式:(?<=XP|7|8)Windows 能匹配 7Windows 中的“Windows”蛤肌,但不能匹配 10Windows 中的“Windows”。 |
(?<!exp) |
斷言自身出現(xiàn)的位置的前面不能匹配表達式 exp展东,(?<!=exp2)exp1:查找前面不是 exp2 的 exp1炒俱。 | 表達式:(?<!XP|7|8)Windows 能匹配 10Windows 中的“Windows”,但不能匹配 7Windows 中的“Windows”砸王。 |
exp :expression(表達式)
匹配模式
類型 | 模式 | 說明 |
---|---|---|
IGNORECASE |
忽略大小寫模式 | 匹配時忽略大小寫谦铃。(正則默認是區(qū)分大小寫的) |
SINGLELINE |
單行模式 | 整個文本看作一個字符串,只有一個開頭一個結(jié)尾 |
MULTILINE |
多行模式 | 每行都是一個字符串瘪菌。在多行模式下控嗜,如果需要僅匹配字符串開始和結(jié)束位置骡显,可以使用 \A 和 \Z |
3、Python 正則表達式
如果使用編輯語言來執(zhí)行正則表達式呢壁顶?所有語言都是相通的溜歪,這是記錄了之前使用 Python 的 re 模塊做正則匹配的功能。
compile 和 match 函數(shù)
re.compile
函數(shù)用于編譯正則表達式调衰,生成一個正則表達式( Pattern )對象嚎莉,供 match()沛豌、search() 等函數(shù)使用加派。
re.match
嘗試從字符串的起始位置匹配一個模式芍锦,如果字符串開始不符合正則表達式,就返回 None 饶米。
result = re.match(pattern, string)
等價于
prog = re.compile(pattern)
result = prog.match(string)
注:如果需要多次使用這個正則表達式的話,使用
re.compile()
保存這個正則對象以便復用匹配多個字符串照瘾,可以讓程序更加高效析命。
search 函數(shù)
re.search
掃描整個字符串并返回第一個成功的匹配鹃愤。如果沒有匹配完域,就返回一個 None 吟税。
re.search(pattern, string, flags=0)
示例:
>>> re.search('iHTCboy', 'www.iHTCboy.com')
>>>
<re.Match object; span=(4, 11), match='iHTCboy'>
我們可以使用 group(num)
或 groups()
匹配對象函數(shù)來獲取匹配表達式肠仪。
>>> searchObj = re.search( r'(.*) are (.*?) .*', "iHTCboy are my nikename)
>>> print(searchObj.group())
>>> print(searchObj.groups())
>>> print(searchObj.group(1))
>>> print(searchObj.group(2))
>>>
iHTCboy are my nikename
('iHTCboy', 'my')
iHTCboy
my
findall 函數(shù)
re.findall
在字符串中找到正則表達式所匹配的所有子串异旧,并返回一個列表,如果沒有找到匹配的荤崇,則返回空列表天试。
re.findall(pattern, string, flags=0)
對
string
返回一個不重復的pattern
的匹配列表然低,string
從左到右進行掃描雳攘,匹配按找到的順序返回吨灭。如果樣式里存在一到多個組刑巧,就返回一個組合列表无畔;就是一個元組的列表(如果樣式里有超過一個組合的話)浑彰≌蓿空匹配也會包含在結(jié)果里。
比如查找字符串中的所有數(shù)字:
>>> result2 = re.findall(r'\d+', 'abc123d4efg567')
>>>
['123', '4', '567']
查找不是以 4诉濒、7 結(jié)尾的手機號碼(11位)手機號碼:
>>> result2 = re.findall(r'^1\d{9}[0-35-68-9]$', 'xxxxx')
>>>
finditer 函數(shù)
和 findall 類似未荒,在字符串中找到正則表達式所匹配的所有子串,并把它們作為一個迭代器返回及志。
re.finditer(pattern, string, flags=0)
搜索string片排,返回一個順序訪問每一個匹配結(jié)果(Match對象)的迭代器:
>>> for m in re.finditer(r'\d+', 'abc123d4efg567'):
>>> print(m.group())
>>>
123
4
567
split 函數(shù)
re.split
方法按照能夠匹配的子串將字符串分割后返回列表。
re.split(pattern, string, maxsplit=0, flags=0)
用
pattern
分開string
困肩。如果maxsplit
非零划纽, 最多進行maxsplit
次分隔, 剩下的字符全部返回到列表的最后一個元素锌畸。
對于規(guī)則的字符串勇劣,比如 abc
我們一般可以用 split 函數(shù)分割,但是如果遇到 a b c
這樣的字符串潭枣,得到的結(jié)果就是 ['a', 'b', '', '', 'c']
比默。所以命咐,你可能需要人工來自己再次過濾,而使用正則表達式來處理窜司,就顯示很輕松:
>>> re.split(r'[\s\,]+', 'a,b, c d')
>>>
['a', 'b', 'c', 'd']
上面的 [\s\,]+
表示匹配 \s
(空格)和 ,
中任意一個至少一次的分割。
對于一個找不到匹配的字符串而言议薪,split 不會對其作出分割产捞。
>>> re.split('a*', 'hello iHTCboy')
>>>
['hello iHTCboy']
sub 函數(shù)
re.sub
用于替換字符串中的匹配項。
re.sub(pattern, repl, string, count=0, flags=0)
返回通過使用
repl
替換在string
最左邊非重疊出現(xiàn)的pattern
而獲得的字符串。 如果樣式?jīng)]有找到衷笋,則不加改變地返回 string。repl
可以是字符串或函數(shù);如為字符串容客,則其中任何反斜杠轉(zhuǎn)義序列都會被處理。 也就是說供置,\n
會被轉(zhuǎn)換為一個換行符,\r
會被轉(zhuǎn)換為一個回車附,依此類推。
比如電話號碼格式可能帶有空格或者-時挎挖,可以替換為空字符串:
>>> re.sub(r'\D', "", "188-8888-8888")
>>>
18888888888
repl
參數(shù)可以是一個函數(shù),用于對匹配的內(nèi)容進行更多的邏輯處理:
# 將匹配的數(shù)字乘以 2
>>> def double(matched):
>>> value = int(matched.group('value'))
>>> return str(value * 2)
>>>
>>> re.sub('(?P<value>\d+)', double, 'abc123d4efg567')
>>>
abc246d8efg1134
總結(jié)
正則表達式的內(nèi)容有非常的多,如果不經(jīng)常使用的話汛闸,可以就會很快忘記。所以别伏,正則其實是不是應(yīng)該記住呢?其實类茂,應(yīng)該是要記住注益,如果記不住厦瓢,要不要緊?其實,是不要緊杉武,因為正則就想查表一下,你如果之前已經(jīng)比較系統(tǒng)的學習過祈搜,忘記了規(guī)則曹铃,看一下本文就大概記起來了秘血。所以忍坷,這就是本文的目的柑肴,總結(jié)性的文章,不需要太多的復雜硕舆,簡單又快捷的總結(jié)。
國慶中秋雙節(jié)快樂凌节!這篇文章應(yīng)該是去年9月就定下來但遲遲沒有動手彪见,現(xiàn)在又過一年了,感嘆生活真快。好好學習,天天快樂~
參考
- 如有疑問,歡迎在評論區(qū)一起討論!
- 如有不正確的地方,歡迎指導钥庇!
注:本文首發(fā)于 iHTCboy's blog参咙,如若轉(zhuǎn)載两入,請注來源