前言
正則表達(dá)式(Regular Expression
)妖爷,就是具有一定規(guī)則的表達(dá)式班利。通過(guò)正則表達(dá)式引擎歼秽,將這些規(guī)則轉(zhuǎn)換為正則表達(dá)式對(duì)象折砸,然后再去文本中搜索能夠與之匹配的字符串莲组。
正則表達(dá)式的語(yǔ)法都是一樣的诊胞,只是不同編程語(yǔ)言的實(shí)現(xiàn)不同,大部分都是師從Perl
锹杈。
對(duì)Perl
語(yǔ)言有所了解的朋友撵孤,學(xué)習(xí)python
正則應(yīng)該是手到擒來(lái)。
正則表達(dá)式入門
Python
中的re
模塊提供了強(qiáng)大的正則表達(dá)式功能竭望。
而第三方模塊regex
提供了與標(biāo)準(zhǔn)庫(kù)re
模塊兼容的API接口, 同時(shí)還提供了額外的功能和更全面的Unicode
支持早直。
匹配字符
大多數(shù)字母和字符只會(huì)匹配自身,例如:python
只會(huì)匹配自己市框,不會(huì)匹配Python
霞扬。
但是有一些字符串,它們不表示自身,而是具有一些特殊含義喻圃,只能通過(guò)\
轉(zhuǎn)義之后才表示自身萤彩。
這些字符包括:
. ^ $ * + ? { } [ ] \ | ( )
.
:
- 在默認(rèn)模式中,匹配除換行外所有字符斧拍,如果指定了
DOTALL
標(biāo)簽雀扶,則表示任意字符
import re
"""
re.findall(pattern, string, flags=0)
pattern: 匹配規(guī)則,字符串
string: 需要去匹配的字符串
從左到右進(jìn)行掃描肆汹,匹配按找到的順序返回愚墓。如果樣式里存在一個(gè)或多個(gè)組,就返回一個(gè)組合列表
"""
re.findall('ab.', 'abc')
# Out[1]: ['abc']
re.findall('ab.', 'ab\n')
# Out[2]: []
re.findall('ab.', 'ab\n', re.DOTALL)
# Out[3]: ['ab\n']
^
:
- 匹配字符串的開(kāi)頭昂勉, 如果是
MULTILINE
模式浪册,匹配每行開(kāi)頭(\n
之后)的首個(gè)符號(hào)。 - 在字符集中可表示'非'岗照,
[^a]
表示除字符a
之外的字符村象。
re.findall('^ab', 'abcda\nabddd')
# Out[4]: ['ab']
re.findall('^ab', 'abcda\nabddd', re.MULTILINE)
# Out[5]: ['ab', 'ab']
re.findall('[^a]', 'aaa\nbbb')
# Out[6]: ['\n', 'b', 'b', 'b']
$
:
- 匹配字符串的末尾,或者在字符串末尾換行符的前一個(gè)字符攒至。
- 在
MULTILINE
模式下匹配每行末尾(\n
之前)的字符厚者。
re.findall('ab$', 'abcdab\nabdab')
# Out[7]: ['ab']
# 上面結(jié)果中的 ab 是 \n 前面的還是后面的呢?進(jìn)行如下測(cè)試迫吐,發(fā)現(xiàn)是后面的 ab 被匹配了
re.findall('ab.$', 'abcdab1\nabdab2')
# Out[8]: ['ab2']
# 在 MULTILINE 模式下库菲,兩個(gè)都被匹配了
re.findall('ab$', 'abcdab\nabdab', re.MULTILINE)
# Out[9]: ['ab', 'ab']
# 而對(duì) $ 在換行結(jié)尾的字符串中匹配時(shí),會(huì)得到兩個(gè)空字符志膀,一個(gè)在換行符之前蝙昙,一個(gè)在字符串的末尾
re.findall('$', 'abcdab1\n')
# Out[10]: ['', '']
*
:
- 匹配前一個(gè)規(guī)則0次或無(wú)限次
re.findall('ab*', 'a')
# Out[11]: ['a']
re.findall('ab*', 'ab')
# Out[12] ['ab']
re.findall('ab*', 'abbbbbbbbbbbbbb')
# Out[13] ['abbbbbbbbbbbbbb']
+
:
- 匹配前一個(gè)規(guī)則1次或無(wú)限次
re.findall('ab+', 'a')
# Out[14]: []
re.findall('ab+', 'ab')
# Out[15] ['ab']
re.findall('ab+', 'abbbbbbbbbbbbbb')
# Out[16] ['abbbbbbbbbbbbbb']
?
:
- 匹配前一個(gè)規(guī)則0次或1次
re.findall('ab?', 'a')
# Out[17]: ['a']
re.findall('ab?', 'ab')
# Out[18] ['ab']
re.findall('ab?', 'abbbbbbbbbbbbbb')
# Out[19] ['ab']
.?
,*?
,??
:
-
.
,*
,?
修飾符都是貪婪的,會(huì)盡可能的匹配更多的字符串 - 貪婪的我梧却,當(dāng)然是贊越多越好呀。
- 而在這些修飾符后面加上
?
败去,便成了非貪婪模式放航,會(huì)盡可能少的匹配字符串
re.findall('<.*>', '<a>bcd>')
# Out[20] ['<a>bcd>']
re.findall('<.*?>', '<a>bcd>')
# Out[21] ['<a>']
{m}
:
- 指定前面的正則表達(dá)式出現(xiàn)的次數(shù),出現(xiàn)次數(shù)必須完全一致圆裕。
re.findall('a{3}', 'aa')
# Out[22]: []
re.findall('a{3}', 'aaaaa')
# Out[23]: ['aaa']
{m, n}
:
- 指定前面的正則表達(dá)式出現(xiàn)的次數(shù)在
m~n
之間广鳍,盡可能多的匹配,匹配的下界是m
吓妆,上界是n
赊时。 - 若缺省
m
,下界為0
行拢,若缺省n
祖秒,為不設(shè)上界,即無(wú)限次。
re.findall('a{3, 5}', 'aaaa')
# Out[24]: []
# 3,5 之間不能添加空格
re.findall('a{3,5}', 'aaaa')
# Out[25]: ['aaaa']
re.findall('a{3,}', 'aaaa')
# Out[26]: ['aaaa']
re.findall('a{,5}', 'aaaa')
# Out[27] ['aaaa', '']
{m, n}?
:
- 即非貪婪模式竭缝,盡可能少的匹配字符串房维。
re.findall('a{3,}?', 'aaaaa')
# Out[28] ['aaa']
\
:
- 轉(zhuǎn)義特殊字符。如
'\.'
只表示.
抬纸,而不再是表示任意字符咙俩。 - 匹配
\
字符需要轉(zhuǎn)義,用\\
表示
re.findall('\.', 'aa')
# Out[29] []
re.findall('\.', 'aa.')
# Out[30] ['.']
- 反斜杠災(zāi)難:反斜杠具有轉(zhuǎn)義作用湿故,如果需要匹配的字符串中存在多個(gè)
\
阿趁,就需要調(diào)加相應(yīng)數(shù)量的\
來(lái)轉(zhuǎn)義
re.findall('\\\\ab', '\\abc') # ['\\ab']
"""
在反復(fù)使用反斜杠的正則中,這會(huì)導(dǎo)致大量重復(fù)的反斜杠坛猪,
并使得生成的字符串難以理解脖阵。
解決方案:
使用 Python 的原始字符串表示法來(lái)表示正則表達(dá)式;
'r' 為前綴的字符串砚哆,反斜杠不再表示轉(zhuǎn)義
"""
re.findall(r'\\ab', '\\abc') # ['\\ab']
re.findall(r'\n', '\n') # ['\n']
[ ]
:
- 表示字符集集合独撇。匹配該字符需要轉(zhuǎn)義
\[,\]
# 1、單獨(dú)列出躁锁,匹配 a纷铣、b 或 c
re.findall('[abc]', 'ab.')
# Out[31]: ['a', 'b']
"""
2、字符范圍:
[a-j]: 表示小寫(xiě)字母 a~j
[1-6]:表示數(shù)字 1~6
轉(zhuǎn)義: 如 [a\-z] 或者它的位置在首位或者末尾([-a] 或 [a-])战转,它就只表示普通字符 '-'搜立。
"""
re.findall('[a\-z]', '-')
# Out[32]: ['-']
re.findall('[-a]', '-')
# Out[33]: ['-']
re.findall('[a-]', '-')
# Out[34]: ['-']
"""
3、特殊字符失去特殊含義
比如 [(+*)] 只會(huì)匹配這幾個(gè)字符 '(', '+', '*', or ')'槐秧。
"""
re.findall('[(+*)]', '+-*/()')
# Out[35] ['+', '*', '(', ')']
"""
4啄踊、字符類
可以使用字符類:\w,\S 等刁标,它們可以匹配的字符由 ASCII 或者 LOCALE 模式?jīng)Q定颠通。
"""
re.findall('[\w]', 'abfagg-/*-')
# Out[36] ['a', 'b', 'f', 'a', 'g', 'g']
"""
5、取反
如果集合首字符是 '^' 膀懈,所有不在集合內(nèi)的字符將會(huì)被匹配
[^^] 將匹配所有字符顿锰,除了 '^'.
^ 如果不在集合首位,就沒(méi)有特殊含義启搂。
"""
# 非 \w 定義的字母
re.findall('[^\w]', 'abfagg-/*-')
# Out[37] ['-', '/', '*', '-']
"""
6硼控、匹配字符 ']'
兩種方法
加上反斜杠
放到集合首位
"""
# 加上反斜杠
re.findall('\]', 'abc]')
# Out[38] [']']
# 放到集合首位
re.findall('[]{}]', ']abc')
# Out[39] [']']
|
:
- 或。
A|B
胳赌,匹配正則表達(dá)式A
或B
牢撼,A
、B
可以是任何正則表達(dá)式疑苫。 - 如果
A
匹配成功熏版,則不會(huì)再匹配B
纷责。 - 匹配
|
字符需要轉(zhuǎn)義,\|
或[|]
re.findall('a|b', 'acb')
# Out[40] ['a', 'b']
re.findall('[|]', 'ab|c')
# Out[41] ['|']
(...)
:
- 小括號(hào)纳决,可以組合表達(dá)式碰逸,匹配括號(hào)內(nèi)的組合表達(dá)式,并標(biāo)注表達(dá)式的開(kāi)始和結(jié)束位置阔加,可用于后續(xù)捕獲
- 每對(duì)小括號(hào)代表一個(gè)組合饵史,可以通過(guò)
\number
的方式引用組合,\1
表示第一個(gè)組合胜榔。 - 要匹配字符
(
或者)
, 用\(
或\)
, 或者放在字符集合里:[(]
,[)]
胳喷。
re.findall('a(b+)', 'abbb')
# Out[42] ['bbb']
。
re.findall(r'(b)a\1', 'bab')
# Out[43] ['b']
總結(jié)
image.png