正則表達式
正則的元字符
w3c的零基礎(chǔ)教程:https://www.w3cschool.cn/regexp/zoxa1pq7.html
正則表達式30分鐘入門教程:http://deerchao.net/tutorials/regex/regex.htm
正則速查:http://www.uedsc.com/lookup-tables.html
'*','+'和'?' 表示字符重復出現(xiàn)的次數(shù),分別表示“零或更多”,“一次或更多”還有“零次或一次”舍咖。
'*','+'和'?' 相當于"{0,}"列荔,"{1,}"和"{0,1}"浸赫。
"ab*":表示一個字符串有一個a后面跟著零個或若干個b害幅。("a", "ab", "abbb",……)绘沉;
"ab+":表示一個字符串有一個a后面跟著至少一個b或者更多营搅;#貪婪匹配云挟,盡可能多的匹配
"ab?":表示一個字符串有一個a后面跟著零個或者一個b;#非貪婪匹配转质,盡可能少的匹配
"a?b+$":表示在字符串的末尾有零個或一個a跟著一個或幾個b。
"ab{2}":表示一個字符串有一個a跟著2個b("abb")帖世;
"ab{2,}":表示一個字符串有一個a跟著至少2個b休蟹;
"ab{3,5}":表示一個字符串有一個a跟著3到5個b。
"hi|hello":表示一個字符串里有"hi"或者"hello"日矫;
"(b|cd)ef":表示"bef"或"cdef"赂弓;
"(a|b)*c":表示一串"a""b"混合的字符串后面跟一個"c";
[]方括號是字符集合哪轿,表示匹配方括號中所包含的任意一個字符
中括號里的^稱為脫字符盈魁,表示不匹配集合中的字符
"a.[0-9]":表示一個字符串有一個"a"后面跟著一個任意字符和一個數(shù)字;
"^.{3}$":表示有任意三個字符的字符串(長度為3個字符)窃诉;
"[ab]":表示一個字符串有一個"a"或"b"(相當于"a|b")杨耙;
"[a-d]":表示一個字符串包含小寫的'a'到'd'中的一個(相當于"a|b|c|d"或者"[abcd]");
"^[a-zA-Z]":表示一個以字母開頭的字符串飘痛;
"[0-9]%":表示一個百分號前有一位的數(shù)字珊膜;
",[a-zA-Z0-9]$":表示一個字符串以一個逗號后面跟著一個字母或數(shù)字結(jié)束。
"%[^a-zA-Z]%"表示兩個百分號中間不應(yīng)該出現(xiàn)字母
[^good] 匹配除了good這幾個字母以外的所有字符宣脉,
[^0-9] 匹配所有的非數(shù)字字符
'''
^ 行首匹配车柠,和在[]里的^不是一個意思,注意:寫在最前面塑猖,表示一個字符串的開始
$ 行尾匹配竹祷,注意:寫在正則最后面,表示一個字符串的結(jié)束
. 匹配除換行符以外的任意字符
說明:下方的x羊苟,y均為假設(shè)的普通字符塑陵,n,m(非負整數(shù))践险,不是正則表達式的元字符
(xyz) 匹配小括號內(nèi)的xyz(作為一個整體去匹配)
x? 匹配0個或者1個x
x* 匹配0個或者任意多個x(.*表示匹配0個或者任意多個字符(換行符除外))
x+ 匹配至少一個x
x{n,} 匹配至少n個x
x{n} 匹配確定的n個x(n是一個非負整數(shù))
x{n,m} 匹配至少n個最多m個x猿妈,注意n<=m
x|y |表示或,匹配的是x或y
\d 匹配數(shù)字巍虫,效果同[0-9]
\D 匹配非數(shù)字字符彭则,效果同[^0-9]
\w 匹配數(shù)字,字母和下劃線占遥,效果同[0-9a-zA-Z_]
\W 匹配非數(shù)字俯抖,字母和下劃線,效果同[^0-9a-zA-Z_ ]
\s 匹配任意的空白符(空格瓦胎、回車芬萍、換行尤揣、制表、換頁)柬祠,效果同[\r\n\t\f]
\S 匹配任意的非空白符北戏,效果同[^\f\n\r\t]
'''
注意:
通常情況下?與*或者是+一起連用漫蛔,來起到一個限制貪婪匹配的作用
*與+一般情況下與“.”,代表匹配任意多個任意字符
'''
\A 匹配字符串開始嗜愈,它和^的區(qū)別是,\A只匹配整個字符串的開頭莽龟,即使在re.M模式(,flags=re.m)下也不會匹配其他行的行首
\Z 匹配字符串結(jié)束蠕嫁,它和$的區(qū)別是,\Z只匹配整個字符串的結(jié)束毯盈,即使在re.M模式下也不會匹配其它行的行尾
注意:若不指定re.M模式剃毒,則^與\A,$與\Z匹配結(jié)果相同。
\b 匹配一個單詞的邊界搂赋,也就是指單詞和空格的位置赘阀,'er\b'可以匹配never,不能匹配nerve厂镇。
注意:當\b添加在單詞左邊的時候纤壁,它會從單詞左邊的邊界開始匹配,
當\b添加添加單詞的右邊的時候,它會從單詞的右邊邊界開始匹配.
若想匹配整個單詞捺信,我們需要給這個單詞左右兩邊都添加\b
\B 匹配非單詞邊界
#注意:當\B寫在左邊酌媒,它表示非左邊邊界開始匹配
當\B寫在右邊,它表示非右邊邊界開始匹配
若單詞兩邊都有\(zhòng)B,它只匹配單詞非邊界中含有字符迄靠。
'''
為了逐字表達秒咨,你必須在"^.$()|[]+?{"這些字符前*加上轉(zhuǎn)義字符\''。
請注意在方括號中掌挚,不需要轉(zhuǎn)義字符雨席。
貪婪與懶惰
當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符吠式。
以這個表達式為例:a.b陡厘,它將會匹配最長的以a開始,以b結(jié)束的字符串特占。如果用它來搜索aabab的話糙置,它會匹配整個字符串aabab。這被稱為貪婪*匹配是目。
有時谤饭,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式揉抵,只要在它后面加上一個問號?亡容。
這樣.?*就意味著匹配任意數(shù)量的重復,但是在能使整個匹配成功的前提下使用最少的重復≡┙瘢現(xiàn)在看看懶惰版的例子吧:
a.?b匹配最短的闺兢,以a開始,以b結(jié)束的字符串辟汰。如果把它應(yīng)用于aabab*的話列敲,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。
為什么第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)帖汞?簡單地說,因為正則表達式有另一條規(guī)則凑术,比懶惰/貪婪規(guī)則的優(yōu)先級更高:最先開始的匹配擁有最高的優(yōu)先權(quán)翩蘸。
代碼/語法 | 說明 |
---|---|
*? | 重復任意次,但盡可能少重復 |
+? | 重復1次或更多次淮逊,但盡可能少重復 |
?? | 重復0次或1次催首,但盡可能少重復 |
{n,m}? | 重復n到m次,但盡可能少重復 |
{n,}? | 重復n次以上泄鹏,但盡可能少重復 |
練習題
'''功能1:提壤扇巍:you...man'''
str1 = "you are a good man,you are a nice man ,you are a great man,you are a..."
print(re.findall(r"you.*?\bman\b",str1))
#\b的用法
str1 = "good man,you are a nice man ,you are a great man,you are a..."
print(re.findall(r"\bman\b",str1)) # ['man', 'man', 'man']
'''功能2:/* part1 */ /* part2 */'''
print(re.findall(r"/\*.*?\*/",r"/* part1 */ /* part2 */"))#\轉(zhuǎn)義字符給*轉(zhuǎn)義
'''功能3:判斷電話號碼是否以134開頭'''
print(re.findall("^134\d{8}$","12345678901"))
'''
功能4:判斷QQ號碼是否合法:
1.位數(shù)6~10
2.全部是數(shù)字
3.不能以0開頭
'''
^[1-9]\d{5,9}$
'''
功能5:校驗普通電話、傳真號碼:可以“+”或數(shù)字開頭备籽,可含有“-” 和 “ ”
'''
/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/
#可以匹配的字符串如:+123 -999 999 舶治; +123-999 999 ;123 999 999 车猬;+123 999999等
'''功能6:校驗URL'''
/^http[s]{0,1}:\/\/.+$/
或 /^http[s]{0,1}:\/\/.{1,n}$/ (表示url串的長度為length(“https://”) + n )
'''功能7:校驗密碼:只能輸入6-20個字母霉猛、數(shù)字、下劃線'''
^(\w){6,20}$
#功能8:對用戶輸入的數(shù)據(jù)進行限制6位0或者1珠闰,若不是則重新輸入惜浅。
def test_num():
while True:
num = input("請輸入一位6位的中獎號碼(0/1)組成:")
res = re.findall("^[01]{6}$", num)
if len(res) == 1:
return num
else:
print("輸入非法,請重新輸入伏嗜。坛悉。。")
continue
'''
功能9
1.身份證正則
2.電話號碼的正則
3.郵箱正則
封裝成一個功能模塊承绸。
'''
import re
def checkIdcard(idcard):
Errors = ['驗證通過!', '身份證號碼位數(shù)不對!', '身份證號碼出生日期超出范圍或含有非法字符!', '身份證號碼校驗錯誤!', '身份證地區(qū)非法!']
area = {"11": "北京", "12": "天津", "13": "河北", "14": "山西", "15": "內(nèi)蒙古", "21": "遼寧", "22": "吉林", "23": "黑龍江",
"31": "上海",
"32": "江蘇", "33": "浙江", "34": "安徽", "35": "福建", "36": "江西", "37": "山東", "41": "河南", "42": "湖北", "43": "湖南",
"44": "廣東", "45": "廣西", "46": "海南", "50": "重慶", "51": "四川", "52": "貴州", "53": "云南", "54": "西藏", "61": "陜西",
"62": "甘肅", "63": "青海", "64": "寧夏", "65": "新疆", "71": "臺灣", "81": "香港", "82": "澳門", "91": "國外"}
idcard = str(idcard)
idcard = idcard.strip()
idcard_list = list(idcard)
# 地區(qū)校驗
key = idcard[0: 2] # TODO: cc 地區(qū)中的鍵是否存在
if key in area.keys():
if (not area[(idcard)[0:2]]):
return Errors[4]
else:
return Errors[4]
# 15位身份號碼檢測
if (len(idcard) == 15):
if ((int(idcard[6:8]) + 1900) % 4 == 0 or (
(int(idcard[6:8]) + 1900) % 100 == 0 and (int(idcard[6:8]) + 1900) % 4 == 0)):
erg = re.compile(
'[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$') # //測試出生日期的合法性
else:
ereg = re.compile(
'[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$') # //測試出生日期的合法性
if (re.match(ereg, idcard)):
return Errors[0]
else:
return Errors[2]
# 18位身份號碼檢測
elif (len(idcard) == 18):
# 出生日期的合法性檢查
# 閏年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
# 平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if (int(idcard[6:10]) % 4 == 0 or (int(idcard[6:10]) % 100 == 0 and int(idcard[6:10]) % 4 == 0)):
ereg = re.compile(
'[1-9][0-9]{5}(19[0-9]{2}|20[0-9]{2})((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$') # //閏年出生日期的合法性正則表達式
else:
ereg = re.compile(
'[1-9][0-9]{5}(19[0-9]{2}|20[0-9]{2})((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$') # //平年出生日期的合法性正則表達式
# //測試出生日期的合法性
if (re.match(ereg, idcard)):
# //計算校驗位
S = (int(idcard_list[0]) + int(idcard_list[10])) * 7 + (int(idcard_list[1]) + int(idcard_list[11])) * 9 + (
int(
idcard_list[2]) + int(idcard_list[12])) * 10 + (
int(idcard_list[3]) + int(idcard_list[13])) * 5 + (int(
idcard_list[4]) + int(idcard_list[14])) * 8 + (int(idcard_list[5]) + int(idcard_list[15])) * 4 + (int(
idcard_list[6]) + int(idcard_list[16])) * 2 + int(idcard_list[7]) * 1 + int(idcard_list[8]) * 6 + int(
idcard_list[9]) * 3
Y = S % 11
M = "F"
JYM = "10X98765432"
M = JYM[Y] # 判斷校驗位
if (M == idcard_list[17]): # 檢測ID的校驗位
return Errors[0]
else:
return Errors[3]
else:
return Errors[2]
else:
return Errors[1]
re模塊常用函數(shù)
complie()
'''
re.compile(patten,flags=0)
參數(shù)一:正則表達式
參數(shù)二:標志位re.M
功能:返回一個編譯正則的對象
優(yōu)點:
提高效率裸影,對于常用的一些正則我們將其編譯為對象,需要正則的的時候八酒,調(diào)用此對象即可
'''
com = re.compile("^134\d{8}")
print(com.findall("1234345566676"))
print(com.findall("13455666761"))
match()
'''
re.match(patten,string,flags=0)
功能:只在字符串開始的位置進行匹配空民,匹配成功的返回一個匹配對象,匹配失敗的時候返回None
注意:這個方法并不是完全匹配,若patten匹配到最后仍有剩余字符串界轩,仍然視為匹配成功
若想完全匹配可以在表達式的結(jié)尾添加”$“.
'''
print(re.match("134\d{8}$","1345566677711"))
print(re.match("134\d{8}","1345566677711"))
search()函數(shù)
'''
re.search(patten,string,flags=0)
功能:匹配整個字符串画饥,返回第一個匹配結(jié)果【匹配對象】
若找不到就返回None。
'''
print(re.search(r"\bgood\b","you are a good good man").group())
findall()
'''
re.findall(patten,string,flags=0)
功能:遍歷匹配浊猾,匹配整個字符串抖甘,返回所有的匹配結(jié)果【列表】.
當匹配失敗的時候,返回一個空的列表葫慎。
'''
print(re.findall("good","you are a goods good man"))
p = re.compile(r"\d+")
print(p.findall('o1n2m3k4'))
sub()
'''
re.sub(patten,repl,string,count,flags)
替換string中每一個匹配的子串后返回替換后的【新字符串】衔彻。
參數(shù)一:要匹配的字符串【舊串】
參數(shù)二:替換的字符串 【新串】
參數(shù)三:傳入的字符串
參數(shù)四:指定替換的次數(shù)【若不指定則默認為0,全部替換】
參數(shù)五:標志位
'''
print(re.sub("\d+","\t","hello122hello222hello11113",count=2))
print(re.sub("\d+","\t","hello122hello222hello11113"))
text = "Bob is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))
split()
'''
re.split(patten,string[,maxsplit])
功能:以指定的匹配正則的字符串來進行切片偷办,返回一個【列表】
注意:當maxsplit不指定的時候艰额,默認整個字符串全部切片。
'''
print(re.split("\d+","hello122hello222hello11113",maxsplit=2))
正則表達式修飾符 - 可選標志
正則表達式可以包含一些可選標志修飾符來控制匹配的模式椒涯。修飾符被指定為一個可選的標志柄沮。多個標志可以通過按位 OR(|) 它們來指定。如 re.I | re.M 被設(shè)置成 I 和 M 標志:
修飾符 | 描述 |
---|---|
re.I | 使匹配對大小寫不敏感 |
re.L | 做本地化識別(locale-aware)匹配 |
re.M | 多行匹配废岂,影響 ^ 和 $ |
re.S | 使 . 匹配包括換行在內(nèi)的所有字符 |
re.U | 根據(jù)Unicode字符集解析字符祖搓。這個標志影響 \w, \W, \b, \B. |
re.X | 該標志通過給予你更靈活的格式以便你將正則表達式寫得更易于理解。 |