python使用正則表達式之前需要先倒入re模塊
import re
可選標志位
re.A |
ASCII,使得 \w,\W,\b,\B,\s 和 \S 只匹配 ASCII 字符,而不匹配完整的 Unicode 字符。這個標志僅對 Unicode 模式有意義,並忽略字節模式。 |
re.I |
IGNORECASE,字符類和文本字符串在匹配的時候不區分大小寫 |
re.L |
LOCALE,使得 \w,\W,\b 和 \B 依賴當前的語言(區域)環境,而不是 Unicode 數據庫 |
re.M |
MULTILINE,通常 ^ 只匹配字符串的開頭,而 $ 則匹配字符串的結尾。當這個標志被設置的時候,^ 不僅匹配字符串的開頭,還匹配每一行的行首;& 不僅匹配字符串的結尾,還匹配每一行的行尾。 |
re.S |
DOTALL,使 . 匹配包括換行符在內的所有字符 |
re.X |
VERBOSE,這個標志使你的正則表達式可以寫得更好看和更有條理,因為使用了這個標志,空格會被忽略(除了出現在字符類中和使用反斜杠轉義的空格);這個標志同時允許你在正則表達式字符串中使用注釋,# 符號后邊的內容是注釋,不會遞交給匹配引擎(除了出現在字符類中和使用反斜杠轉義的 #)。 |
可以同時使用多個標志位,方法:re.search( r'正則表達式', '字符串', re.M|re.I)
特殊字符
\d |
匹配任何十進制數字;相當於類 [0-9] |
\D |
與 \d 相反,匹配任何非十進制數字的字符;相當於類 [^0-9] |
\s |
匹配任何空白字符(包含空格、換行符、制表符等);相當於 [ \t\n\r\f\v] |
\S |
匹配任何非空白字符;相當於類 [^\t\n\r\f\v] |
\w |
匹配字母數字及下划線 |
\W |
匹配非字母數字及下划線 |
\b |
匹配單詞的開始或結束 |
\B |
匹配非單詞邊界 |
元字符
| |
或操作符,a | b匹配a或b |
^ |
匹配字符串的開頭,如果設置了 MULTILINE 標志,就會變成匹配每一行的起始位置。 |
$ |
匹配字符串的末尾。如果設置了 MULTILINE 標志,就會變成匹配每一行的結束位置。 |
. |
匹配任意字符,除了換行符,如果設置了DOTALL標志,則可以匹配包括換行符的任意字符。 |
[abc] |
匹配括號中的a,b,c任意單個字符,而不是abc字符串 |
[^abc] |
匹配除了a,b,c之外的任意字符 |
* |
匹配前一個字符0次或多次 |
+ |
匹配前一個字符1次或多次 |
? |
匹配前一個字符0次或1次 |
{n} |
精確匹配前一個字符 n次,例如a{3}b,可以匹配aaab |
{,n} |
匹配前一個字符0次到n次 |
{n,} |
匹配前一個字符 n次到無限次 |
{m,n} |
匹配前一個字符 m 到 n 次 |
\1...\9 |
匹配第n個分組的內容。(abc)小括號括起來的為一組\1匹配第一個小括號的組... |
1.compile函數:用於編譯正則表達式,生成一個正則表達式對象
p = re.compile(r'正則表達式'[, 可選標志位]) p.search('待匹配內容').group()
2.match函數:從字符串的起始位置開始匹配,如果起始位置匹配不成功返回none
re.match(r'正則表達式','字符串'[,可選標志位])
匹配對象包含了很多方法和屬性,以下幾個是最重要的
group() | 返回匹配的字符串 |
start() | 返回匹配的開始位置 |
end() | 返回匹配的結束位置 |
span() | 返回一個元組表示匹配位置(開始,結束) |
3.search函數:掃描整個字符串並返回第一個成功匹配的子串
re.search(r'正則表達式','字符串'[,可選標志位])
匹配對象同樣包含了很多方法和屬性
group() | 返回匹配的字符串 |
start() | 返回匹配的開始位置 |
end() | 返回匹配的結束位置 |
span() | 返回一個元組表示匹配位置(開始,結束) |
4.findall函數:掃描整個字符串,並返回一個列表,所有成功匹配的子串,如果沒有匹配成功返回none
r = re.findall('\d+','111aaa222bbb333ccc') print(r) ['111', '222', '333'] #當正則表達式加上括號時,返回結果會優先顯示括號內匹配到的內容 #如果不想要優先顯示括號內匹配到的內容,可以在括號內頂格加上?: #(?:正則表達式)
5.finditer函數:和findall類似,成功匹配時返回一個迭代器
p = re.compile('\d+') iterator = p.finditer('3只小甲魚,15條腿,還有3條去了哪里?') for match in iterator: print (match.group())
6.sub函數:替換,類似字符串的replace
>>> r = re.sub('\d+', 'b', 'aaa111aaa222aaa333') >>> print(r) aaabaaabaaab
7.split函數:切割
>>> r = re.split('\d+','111aaa222bbb333ccc') >>> print(r) ['', 'aaa', 'bbb', 'ccc'] #可以加上切割次數 >>> r = re.split('\d+','111aaa222bbb333ccc',1) >>> print(r) ['', 'aaa222bbb333ccc'] #當需要顯示切割的內容時,可以在正則表達式兩邊加上括號 #打印時會把切割的內容一並顯示 >>> r = re.split('(\d+)','111aaa222bbb333ccc') >>> print(r) ['', '111', 'aaa', '222', 'bbb', '333', 'ccc']
8.分組命名
定義分組:(?P<name>正則表達式) 分組引用:(?P=name) >>> r = re.search('(?P<tag><\w+>)(?P<t>\w+)(?P=tag)','<h1>haha<h1>') >>> print(r.group("t")) haha >>> print(r.group("tag")) <h1>
貪婪 VS 非貪婪
當重復一個正則表達式時,如果使用 a*,那么結果是盡可能多地去匹配。當你嘗試匹配一對對稱的定界符,例如 HTML 標志中的尖括號,默認的貪婪模式會使得你很困擾。
我們來看下例子:
>>> s = '<html><head><title>Title</title>' >>> len(s) 32 >>> print(re.match('<.*>', s).span()) (0, 32) >>> print(re.match('<.*>', s).group()) <html><head><title>Title</title>
RE 匹配在 <html> 的 < 后,.* 消耗掉字符串的剩余部分。由於正則表達式默認是貪婪的原因,RE 必須從字符串的尾部一個字符一個字符地回溯,直到找到匹配的 >。大家看到,按照這種方法,最后找到匹配內容竟是 <html> 的 < 開始,到</title> 的 > 結束。顯然這不是你想要的結果。
在這種情況下,解決方案是使用非貪婪的限定符 *?、+?、?? 或 {m, n}?,盡可能地匹配小的文本。
>>> print(re.match('<.*?>', s).group()) <html>