定義
在編寫處理字符串的程序或網(wǎng)頁時,經(jīng)常會有查找符合某些復(fù)雜規(guī)則的字符串的需要陋葡。正則表達式就是用于描述這些規(guī)則的工具亚亲。
簡而言之:正則表達式就是記錄文本規(guī)則的代碼。
特點:
操作字符串
1.更快的方式操作字符串腐缤;(表單校驗捌归,數(shù)據(jù)匹配...)
2.普通字符串操作無法做到的,或者很難做的正則很容易搞定A朐痢O鳌!
使用場景:
1.表單校驗
2.api 里面也需要正則
3.[\u4e00-\u9fa5] 中文匹配 Unicode 編碼中文匹配
正則表達式代碼體驗
# Python 解釋器為我們提供了一個使用正則的模塊剃浇,這個模塊叫做re(regex)
import re
if __name__ == '__main__':
# 1.match():匹配 -> object
# group():通過匹配后门扇,可以使用group()獲取內(nèi)容
obj = re.match(r"jovelin", "jovelin")
print(obj.group()) # -> jovelin
# 2.如果被匹配的內(nèi)容多余正則;(只返回開頭匹配的部分)
obj = re.match(r"jovelin", "jovelin.cn")
print(obj.group()) # -> jovelin
# 3.如果開頭部分偿渡,沒有匹配的內(nèi)容臼寄; 那么返回None
obj = re.match(r"jovelin", "www.jovelin.cn")
print(obj) # -> None
print(None, type(None)) # -> None <class 'NoneType'>
常用的元字符
語法 | 說明 |
---|---|
. | 匹配除換行符(\n)以外的任意字符 |
[] | 匹配 [ ] 中列舉的字符 |
\w | \W | 匹配字母或數(shù)字或下劃線或漢字 | 反義 |
\s | \S | 匹配任意的空白符 | 非空白 |
\d | \D | 匹配數(shù)字 [0-9] | 非數(shù)字 |
\b | \B | 匹配單詞的開始或結(jié)束 | 反義 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結(jié)束 |
代碼演示:
# . 匹配任意1個字符(除了 \n)
print(re.match(r'a.b', 'a\nb')) # -> None
# - 在 [] 里代表范圍
print(re.match(r'a[a-c]c', 'abc').group()) # -> abc
# 在 [] 里面也想使用 - 那么需要 \ 轉(zhuǎn)義
print(re.match(r'a[a\-c]c', 'a-c').group()) # -> a-c
# \b用法 與 ^ $ 相似,不過 \b 只匹配單詞溜宽,\B 只匹配非單詞
print(re.match(r"\b\w+\b", "0_9_a_z_A_Z漢字").group()) # -> 0_9_a_z_A_Z
print(re.match(r"\B\W+\B", "!@#$%^&*").group()) # -> !@#$%^&*
# ^ 匹配字符串開頭
# $ 匹配字符串結(jié)尾
print(re.match(r'[\w\W]*$', '0_9_a_z_A_Z漢字!@#$%^&* \n\t').group()) # -> 0_9_a_z_A_Z漢字!@#$%^&*
# 注意: ^ 如果出現(xiàn)在 [] 中吉拳,代表的是取反! (想要使用 ^,可以轉(zhuǎn)義 \)
print(re.match(r'^[\^]$', '^').group()) # -> ^
print(re.match(r'^[^^]$', '^')) # -> None
print(re.match(r'^[^47]$', '47')) # -> 47
常用的限定符(量詞)
語法 | 說明 | 備注 |
---|---|---|
* | 重復(fù)零次或更多次 | >=0 |
+ | 重復(fù)一次或更多次 | >=1 |
? | 重復(fù)零次或一次 | 0|1 |
{n} | 重復(fù)n次 | ==n |
{n,} | 重復(fù)n次或更多次 | >=n |
{n,m} | 重復(fù)n到m次 | n<=X<=m |
代碼演示:
# * 匹配前一個字符出現(xiàn)0次或者無限次,即可有可無 (>=0)
print(re.match(r'a*b', 'b').group()) # -> b
# + 匹配前一個字符出現(xiàn)1次或者無限次适揉,即至少有1次 (>=1)
print(re.match(r'a+b', 'b')) # -> None留攒,必須要 1 個 a
# {n} 匹配前一個字符出現(xiàn)n次 == n (== n)
print(re.match(r'a{2}b', 'ab')) # -> None,必須要 2 個 a
# {n,m} 匹配前一個字符出現(xiàn): n次<= 前一個字符 <=m次 (n<=X<=m)
print(re.match(r'a{2,5}b', 'ab')) # -> None嫉嘀,a 的次數(shù)必須是 2<=a<=5
案例:
1.校驗手機號
import re
def isMobileNumber(tel):
"""
校驗手機號是否正確
"""
if re.match(r"^[1-][34578-]\d{9}$", tel) is None:
return False
else:
return True
print(isMobileNumber("18819950820"))
2.校驗郵箱
import re
"""
郵箱名稱部分為: [a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){0,4}
域名部分: [a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+
連起來 ^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){0,4}@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){1,2}$
"""
def isEmail(email):
"""校驗郵箱是否正確"""
if re.match(r"^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){0,4}@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+){1,2}$", email) is None:
return False
else:
return True
print(isEmail("jovelin@163.com"))
print(isEmail("jovelin.dev@gmail.com"))
print(isEmail("jovelin@163.com.cn"))
print(isEmail("jovelin.dev@gmail.com.cn"))
分組
用小括號來指定子表達式(也叫做分組)炼邀,然后你就可以指定這個子表達式的重復(fù)次數(shù)了,你也可以對子表達式進行其它一些操作剪侮。
語法 | 說明 |
---|---|
(abc) | 將括號中字符作為一個分組 |
| | 匹配左右任意一個表達式 |
\num | 引用分組num匹配到的字符串 |
(?P<name>) | 分組起別名 |
(?P=name) | 引用別名為name分組匹配到的字符串 |
代碼演示:
# (abc) 將括號中字符作為一個分組
print(re.match(r'(aaa)bbb(ccc)', 'aaabbbccc').group())
# 一個括號就是一個分組拭宁; group():參數(shù)代表分組的編號镇匀;寫 0 或者不寫時敬锐,獲取全部;
print(re.match(r'(aaa)bbb(ccc)', 'aaabbbccc').group())
print(re.match(r'(aaa)bbb(ccc)', 'aaabbbccc').group(0))
print(re.match(r'(aaa)bbb(ccc)', 'aaabbbccc').group(1))
# | 匹配左右任意一個表達式(和 [] 相似)
print(re.match(r'aaa(xxx|yyy|zzz)bbb', 'aaaxxxbbb').group())
# \num 引用分組 num 匹配到的字符串
# 前后保證一致纵竖,要使用到分組彩匕!
print(re.match(r'^<(\w+)>\w+</\1>$', '<html>nihao</html>').group())
print(re.match(r'^<(\w+)><(\w+)>\w+</\2></\1>$', '<html><div>nihao</div></html>').group())
# (?P<name>正則) 分組起別名
# (?P=name) 引用別名為name分組匹配到的字符串
print(re.match(r'^<(?P<re1>\w+)><(?P<re2>\w+)>\w+</(?P=re2)></(?P=re1)>$', '<html><div>jovelin</div></html>').group())
正則高級 API(4個)
語法 | 說明 |
---|---|
search() | 搜索字符串中符合正則表達式的內(nèi)容 -> 只返回第一個 |
findall() | 搜索字符串中符合正則表達式的內(nèi)容 -> 返回一個列表 |
sub() | 替換字符串中符合正則的內(nèi)容 -> 替換后的字符串 |
split() | 按照指定正則切割字符串 -> 返回列表 |
代碼演示:
import re
# 1.search()
print(re.search(r"\d+", "aaa111bbb222ccc333ddd").group())
# 2.findall()
print(re.findall(r"\d+", "aaa111bbb222ccc333ddd"))
# 3.sub()
print(re.sub(r"\d+", "***", "aaa111bbb222ccc333ddd"))
# sub(正則, 替換成***, 被操作的字符串, 替換次數(shù))
print(re.sub(r"\d+", "***", "aaa111bbb222ccc333ddd", 2))
# 4.split()
print(re.split(r"\d+", "aaa111bbb222ccc333ddd eee"))
print(re.split(r"\d+|\s", "aaa111bbb222ccc333ddd eee"))
r 的作用
讓程序把正則直接當(dāng)做正則看腔剂;(不是從字符串開始解釋)
# c:\aaa\bbb\ccc
print('c:\aaa\bbb\ccc')
print('c:\\aaa\\bbb\\ccc')
# 問題:在字符串中寫 \ 時會轉(zhuǎn)義,需要寫成 \\
# 不寫 r 時 \\\\ -> \\
print(re.match('c:\\\\aaa\\\\bbb\\\\ccc', 'c:\\aaa\\bbb\\ccc').group())
# 寫 r 時 \\ -> \\
print(re.match(r'c:\\aaa\\bbb\\ccc', 'c:\\aaa\\bbb\\ccc').group())
貪婪/非貪婪
貪婪:(量詞在自己的范圍內(nèi)驼仪,取最多...)
非貪婪:(量詞在自己的范圍內(nèi)掸犬,取最少... )
非貪婪用法:量詞后面加?
print('貪婪', re.match(r'a+', 'aaa').group()) # -> aaa
# 量詞后面加?
print('非貪婪', re.match(r'a+?', 'aaa').group()) # -> a
print('貪婪', re.match(r'a{1,2}', 'aaa').group()) # -> aa
# 量詞后面加?
print('非貪婪', re.match(r'a{1,3}?', 'aaa').group()) # -> a
更多參考內(nèi)容: http://deerchao.net