正則表達式(正則、regular、re)是 Python 中最多見的編程技巧,不少時候,一個好的正則表達式能夠抵上幾十行代碼。好比:匹配(校驗)郵箱、身份證、手機號、IP地址、URL、HTML等。python
正則表達式,其實就是一串特殊的字符序列,而這串字符序列蘊含着事先定義好的 模式 (規則),能夠用於匹配、校驗其它的字符串(文本、網頁等)。正則表達式
但想掌握正則表達式的難度在於,其包括了較多的 基礎模式語法 須要記憶,而且這些基礎模式語法能夠進行組合,產生無窮的變化。編程
因此,不建議死記硬背正則的基礎模式語法,能夠隨用隨查,使用多了,天然就會造成機械記憶了。google
字符範圍匹配spa
正則表達式 | 說明 | 正確 | 錯誤 |
---|---|---|---|
A | 精準匹配單個字符 | A | a |
x|y | 容許出現的2個字符 | y | n |
[xyz] | 字符集合,容許出現集合內任意單個字符 | z | c |
[a-z] [A-Z] [0-9] | 字符範圍 | a D 8 | A a A |
[^xyz] [^0-9] | 集合內字符不容許出現 | 0 A | y 8 |
元字符code
正則表達式 | 說明 | 正確 | 錯誤 |
---|---|---|---|
\d | 匹配任意單個數字 | 8 | i |
\D | 匹配\d規則以外的任意單個字符 | i | 8 |
\w | 匹配任意單個字母數字下劃線 | Y | & |
\W | 匹配\w以外的任意單個字符 | & | Y |
\s | 匹配單個空格 | x | |
\n | 匹配單個換行符 | x | |
. | 匹配任意單個字符(換行符除外) | -- | -- |
\. | 特殊字符,只匹配. | . | 1 |
屢次重複匹配cdn
正則表達式 | 說明 | 正確 | 錯誤 |
---|---|---|---|
A{3} | 精準N次匹配 | AAA | AA |
A{3,} | 最少出現N次 | AAA | AA |
\d{3,5} | 約定出現最少次數與最大次數 | 1234 | 12 |
\d* | 能夠出現零次至無限次,至關於{0,} | 1234 | -- |
\d+ | 最少出現一次,至關於{1,} | 12 | |
\d? | 最多出現一次,至關於{0,1} | 1 | 12 |
定位匹配對象
正則表達式 | 說明 | 正確 | 錯誤 |
---|---|---|---|
^A.* | 頭匹配 | ABC | CBA |
.*A$ | 尾匹配 | CBA | ABC |
^A.*A$ | 全字匹 | ACCCA | ACCC |
import re
# 密碼強度的正則表達式
re_password = re.compile(r'^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$')
複製代碼
同時在 re.compiler(pattern[, flags])
時,可選正則表達式的修飾符,來控制匹配的模式。blog
具體以下表所示:字符串
修飾符 | 描述 |
---|---|
re.I | 使匹配對大小寫不敏感 |
re.L | 作本地化識別(locale-aware)匹配 |
re.M | 多行匹配,影響 ^ 和 $ |
re.S | 使 . 匹配包括換行在內的全部字符 |
re.U | 根據Unicode字符集解析字符。這個標誌影響 \w, \W, \b, \B |
re.X | 該標誌經過給予你更靈活的格式以便你將正則表達式寫得更易於理解 |
re.match(pattern, string, flags=0)
從字符串的起始位置匹配,若是不能起始位置匹配成功的話,則返回 None
,這一點須要咱們特別注意。
其中參數 flags
就是正則表達式的修飾符。
import re
print(re.match(r'hello', 'Hello world', re.I))
print(re.match(r'world', 'Hello world', re.I))
<_sre.SRE_Match object at 0x7f2c7c626648>
None
複製代碼
re.search(pattern, string, flags=0)
與 match
方法不一樣,它能夠掃描整個字符串,並返回第一成功的匹配。
import re
print(re.search(r'hello', 'Hello world', re.I))
print(re.search(r'world', 'Hello world', re.I))
<_sre.SRE_Match object at 0x7fbcf9945648>
<_sre.SRE_Match object at 0x7fbcf9945648>
複製代碼
能夠看到,search
方法成功找到了 world
字符串。
若是咱們想輸出匹配的結果,能夠使用 group
和 groups
。
import re
print(re.search(r'world', 'Hello world', re.I).group(0))
print(re.search(r'(world)', 'Hello world', re.I).groups())
world
('world',)
複製代碼
這裏有一個知識點就是 ()
在正則表達式中應用給 groups
。
還有一點須要特別說明, 正則表達式匹配默認是 貪婪匹配 。
import re
print(re.match(r'^(\d+)(0*)$', '102300').groups())
print(re.match(r'^(\d+?)(0*)$', '102300').groups())
('102300', '')
('1023', '00')
複製代碼
因爲\d+
採用貪婪匹配,直接把後面的 0
所有匹配了,結果 0*
只能匹配空字符串了。
必須讓 \d+
採用非貪婪匹配(也就是儘量少匹配),才能把後面的 0
匹配出來,加個 ?
就可讓 \d+
採用。
match
和 search
只能匹配一次,若是想匹配全部,那麼能夠使用 findall
和 finditer
。
findall(string[, pos[, endpos]]
import re
# 匹配數字
pattern = re.compile(r'\d+')
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
['123', '456']
['88', '12']
複製代碼
finditer(pattern, string, flags=0)
import re
# 匹配數字
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print (match.group())
12
32
43
3
複製代碼
除了單純的匹配以外,還會有 分割 和 替換 的需求,因此下面介紹這兩種方法:
re.split(pattern, string[, maxsplit=0, flags=0])
import re
print(re.split('\W+', 'runoob, runoob, runoob.'))
['runoob', 'runoob', 'runoob', '']
複製代碼
re.sub(pattern, repl, string, count=0, flags=0)
import re
dt = '2020-01-01'
print(re.sub(r'\D', ' ', dt))
2020 01 01
複製代碼
校驗密碼強度:
^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
校驗中文:
^[\\u4e00-\\u9fa5]{0,}$
有數字、26個英文字母或下劃線組成的字符串:
^\\w+$
校驗Email地址:
[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?
校驗身份證號碼
15位:
^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$
18位:
^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$
校驗手機號:
^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$
IP地址:
v4:
\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b
v6:
(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
提取頁面超連接:
(<a\\s*(?!.*\\brel=)[^>]*)(href="https?:\\/\\/)((?!(?:(?:www\\.)?'.implode('|(?:www\\.)?', $follow_list).'))[^"]+)"((?!.*\\brel=)[^>]*)(?:[^>]*)>
校驗日期:
^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
校驗金額:
^[0-9]+(.[0-9]{2})?$
(能夠雙擊直接複製,方便使用)
最後,安利你們一本掘金小冊《深刻理解NLP的中文分詞:從原理到實踐》,讓你從零掌握中文分詞技術,踏入NLP的大門。
若是由於以上內容對你有所幫助,但願你幫忙點個贊、轉個發、評個論。