[元字符] 分組符號正則表達式
a|b 匹配字符a 或 字符b (若是兩個當中有重合部分,把更長的那個放前面)算法
(ab) 匹配括號內的表達式 ,將()做爲一個分組函數
num 引用分組num匹配到的字符串spa
(?P<name>)給分組命名3d
(?P=name)引用別名: 把name分組所匹配到的內容引用到這裏orm
## (1) 正常狀況下用()圓括號進行分組 能夠用\1 反向引用第一個圓括號匹配的內容。對象
## (2) (?:正則表達式) 表示取消優先顯示的功能three
(正則表達式) 把分組的匹配到的內容加到列表,不是分組的匹配匹配到的內容不加到列表中
(?:正則表達式) 把分組的匹配到的內容和沒有分組匹配到的內容一塊兒加到列表裏rem
print(re.findall('.*?_good', 'one_good two_good three_good'))
# 注意從頭開始的,而後進行匹配,匹配搭配_good開始不是任意字符
# ['one_good', ' two_good', ' three_good']
print(re.findall('(.*?)_good', 'one_good two_good three_good'))
# ['one', ' two', ' three']
# 在匹配的時候是須要_good才能符合匹配條件的,可是並無加到列表中
# 只把分組匹配搭配的內容加入到列表中
print(re.findall('(?:.*?)_good', 'one_good two_good three_good'))
# 將匹配到的內容所有加到列表中,不論是分組內的仍是分組外的
# ['one_good', ' two_good', ' three_good']
## (3)| 表明或
# 既想匹配abc 還要匹配 abcd
lst = re.findall("abc|abcd", "abc234abcd234390dbohdq")
print(lst)
# 有缺陷,不可以都匹配到
# ['abc', 'abc']
lst = re.findall("abcd|abc", "abc234abcd234390dbohdq")
print(lst)
# ['abc', 'abcd']
#對.匹配進行解析
用\讓本來有意義的字符變得無心義
.表明任意字符,除了\n
若是想要讓正則匹配有個
用\.讓點的轉義失效
# 匹配小數
# 231.321 3213 312 89.32 0.3231
lst = re.findall("\d+\.\d+", "231.321 3213 312 89.32 0.3231")
# \d+ 表示匹配一個或者多個數字
print(lst)
# ['231.321', '89.32', '0.3231']
# 使用分組的形式來匹配小數和正數
# 不正確版本,加入的是小數部分或空字符
lst = re.findall("\d+(\.\d+)?", "231.321 3213 312 89.32 0.3231")
print(lst)
# ['.321', '', '', '.32', '.3231']
# 正確版
lst = re.findall("\d+(?:\.\d+)?", "231.321 3213 312 89.32 0.3231")
print(lst)
# ['231.321', '3213', '312', '89.32', '0.3231']
# 從字符串中匹配135或171的手機號
print("=========================135")
lst = re.findall("(?:135|171)\d{8}", "135678987654w171skdjfksjkf 11312312317178787887")
print(lst)
lst = re.findall("135\d{8}|171\d{8}", "135678987654w171skdjfksjkf 11312312317178787887")
print(lst)
lst = re.findall("(?:135|171)[0-9]{8}", "135678987654w171skdjfksjkf 11312312317178787887")
print(lst)
# 結果都是:
# ['13567898765', '17178787887']字符串
## (3) (?P<組名>正則表達式) 給這個組起一個名字
## (4) (?P=組名) 引用以前組的名字,把該組名匹配到的內容放到當前位置
import re
#首先是正常分組對這些內容的匹配及結果
strvar = '<h1>sdfsdfsdfsdf</h1>'
lst = re.findall("<(.*?)>(.*?)<(.*?)>",strvar)
print(lst)
# [('h1', 'sdfsdfsdfsdf', '/h1')]
strvar = "123<h1>sdfsdfsdfsdf</h1> 123<h2>ppoo</h2>"
lst = re.findall("<(.*?)>(.*?)<(.*?)>",strvar)
print(lst)
# [('h1', 'sdfsdfsdfsdf', '/h1'), ('h2', 'ppoo', '/h2')]
#反向引用,
# 拿到已經匹配到的值,再引用一次
#引用第一個口號裏面的內容 \1
#引用第二個括號裏面的內容 \2 依次類推
#例:
strvar = "123<h1>sdfsdfsdfsdf</h1> 123<h2>ppoo</h2>"
lst = re.findall(r"<(.*?)>(.*?)</\1>",strvar)
print(lst)
#findall能根據反向匹配,可是不顯示在匹配後的數據裏
# [('h1', 'sdfsdfsdfsdf'), ('h2', 'ppoo')]
#命名分組方式1:
strvar = 'd3j5sdj'
obj = re.search(r"(.*?)\d(.*?)\d(.*?)\1\2",strvar)
print(obj)
# <_sre.SRE_Match object; span=(0, 7), match='d3j5sdj'>
res = obj.group() #對象.方法
print(res)
#search反向引用的數據也匹配到數據中,關於search說明請見正則相關函數
# 結果爲: d3j5sdj
#命名分組方式2:
#用命名分組進行反向引用
obj = re.search("(?P<tag1>.*?)\d(?P<tag2>.*?)\d(?P<tag3>.*?)(?P=tag1)(?P=tag2)",strvar)
print(obj)
# 獲得的是一個對象: <_sre.SRE_Match object; span=(0, 7), match='d3j5sdj'>
res = obj.group()
# 使用對象.方法 的到數據: d3j5sdj
print(res)
#命名分組方式3:
obj = re.search(r"(?P<tag1>.*?)\d(?P<tag2>.*?)\d(?P<tag3>.*?)\1\2",strvar)
print(obj)
# <_sre.SRE_Match object; span=(0, 7), match='d3j5sdj'>
res = obj.group()
print(res)
# 使用對象.方法 的到數據: d3j5sdj
findall 匹配字符串中相應內容,返回列表 [用法: findall("正則表達式","要匹配的字符串")]
search 經過正則匹配出第一個對象返回,經過group取出對象中的值
match 驗證用戶輸入內容
split 切割
sub 替換
finditer 匹配字符串中相應內容,返回迭代器
compile 指定一個統一的匹配規則
上面已經講過很少作講解
經過正則匹配出第一個對象返回,經過group取出對象中的值
Search 經過正則匹配出第一個對象返回(只匹配一次),經過group取出對象中的值
findall 把知足條件的全部值都找出來放到列表裏面返回
search 找到一個知足條件的值就直接返回,扔到一個對象當中
想要獲取對象中的值,用group 對象.group()
# 注意只匹配一次
obj = re.search("\d+", "dohd3093dhdoqhd9023")
# \d+ 表示匹配屢次數字,到不符合中止,search只匹配一次全部是3093
print(obj) # 返回的是一個對象 #<_sre.SRE_Match object; span=(4, 8), match='3093'>
res = obj.group()
print(res) # 3093
# 匹配www.baidu.com 或者 www.sohu.com
obj = re.search("(w{3})\.(baidu|sohu)\.(com)", "www.baidu.com www.sohu.com")
res = obj.group()
#雖然兩個地址都符合條件,可是search只匹配一次
print(res)
#結果: www.baidu.com
obj = re.search("(www)\.(baidu|sohu)\.(com)", "www.sohu.com")
res = obj.group()
print(res) # www.sohu.com
# 數字1 表明第一個括號裏面的內容
res = obj.group(1)
print(res) # www
# 數字2 表明第二個括號裏面的內容
res = obj.group(2)
print(res) # sohu
# 數字2 表明第三個括號裏面的內容
res = obj.group(3)
print(res) # com
# groups 一次性把全部小括號裏面的內容匹配出來
res = obj.groups()
print(res) # ('www', 'sohu', 'com')
# search 和 match 用法同樣,區別在於match 在正則的前面加了一個^條件 [必須以...開頭]
# search 只須要在正則的前面加上^ 就能夠取代 match
strvar = "uuyydfopopopop3434sdf234"
# obj = re.search("^d.*?",strvar) #等價於,match
obj = re.search("d.*?\d", strvar)
res = obj.group()
print(res) # dfopopopop3
# match
obj = re.match("d.*?\d", strvar)
print(obj) # None 必須以d做爲字符串的開頭,全部匹配不到返回None
# res = obj.group()
# print(res)
#例1:
#字符串的方法是將,替換成| 再用字符串切割用| 切割爲列表
strvar = "one|two|three,four"
lst = strvar.replace(",","|").split("|")
print(lst)
#['one', 'two', 'three', 'four']
#使用re的切割方法
strvar = "one,two|three%four"
res = re.split(r"[,|%]",strvar)
#經過多個字符選一個匹配切割最後獲得列表
print(res)
#['one', 'two', 'three', 'four']
#例2:
strvar = "one234234two2three909090four"
res = re.split(r"\d+",strvar)
# 經過用\d+ 爲分界來切割,將獲得的數據返回放入列表
print(res)
# ['one', 'two', 'three', 'four']
#格式: sub(pattern, repl, string, count=0, flags=0)
#例:
strvar = "one,two|three%four"
res = re.sub("[,|%]","-",strvar)
print(res)
# one-two-three-four
#後面能夠選擇替換的次數
#只替換一次
res = re.sub("[,|%]","-",strvar,1)
print(res)
# one-two|three%four
res = re.sub("[,|%]","-",strvar,count=1)
print(res)
# one-two|three%four
#subn 和 sub 用法同樣,最大的區別在返回值,返回一個元組,包含替換的次數
res = re.subn(r"[,|%]","-",strvar)
print(res)
# ('one-two-three-four', 3)
# finditer 和 findall 用法同樣,區別在於返回的是迭代器
strvar = "sdfsdff&*&*%^%234sdfsdfskdjfk3sdf23"
#例:使用findall
lst = re.findall("\d", strvar)
print(lst) # ['2', '3', '4', '3', '2', '3']
#例:使用finditer
res = re.finditer("\d", strvar)
print(res) #<callable_iterator object at 0x0000021398B5ACF8>
from collections import Iterator
print(isinstance(res, Iterator)) # True
it = re.finditer("\d", strvar)
#lst = list(it)
#print(lst)
obj = next(it)
res = obj.group()
print(res)
# 2
for i in it:
res = i.group()
print(res)
# 輸出爲: 3 4 3 2 3
寫一套正則,程序就須要從新編譯一次
同一個正則多處使用,反覆編譯會浪費時間
這樣的話,就可使用compile來定義,終身受益
#例:
rule = re.compile("\d+") #規則是匹配至少一次數字
print(rule) # re.compile('\\d+')
strvar = "sdfsdfs234kjkjk*(*9343dsf3"
# 用search 匹配至少一次數字貪婪算法知道不符合才中止
obj = rule.search(strvar)
# 獲取一個對象
print(obj) # <_sre.SRE_Match object; span=(7, 10), match='234'>
# 對象.方法獲得數據
print(obj.group()) # 234
#使用規則用findall進行匹配
lst = rule.findall(strvar)
# ['234', '9343', '3']
print(lst)
經常使用修飾符說明:
re.I使匹配對大小寫不敏感
re.M 多行匹配,影響 ^ 和 $
re.S使 . 匹配包括換行在內的全部字符
#例1:
strvar = """<h1>sdfsf</H1>
<H1>dd22</h1>
<h1>aabb</H1>"""
# 不受大小寫影響,和不受換行影響結合
lst = re.findall("^<h1>(.*?)</h1>$",strvar,flags=re.M|re.I)
print(lst) # ['sdfsf', 'dd22', 'aabb']
#例2:
strvar = """<h1>sdfsf</h1>
<h1>dd22</h1>
<h1>aabb</h1>"""
#不受多行匹配影響
rule = re.compile("^<h1>(.*?)</h1>$",flags=re.M)
#rule = re.compile("^<h1>(.*?)</h1>$",flags=re.M|re.I)
lst = rule.findall(strvar)
print(lst)
print("===========")
#re.S 使.匹配包括換行在內的全部字符
obj = rule.search(strvar)
print(obj.group())
import re
# 一、匹配整數或者小數(包括正數和負數)
lst = re.findall(r"[+-]*?\d+\.*?\d*?",'-555555 w3213 +321 321.321 321.321')
print(lst)
# 2、匹配年月日日期 格式 2018-12-31
lst = re.findall( '\d{4}-(?:0[0-9])-(?:[0-2]\d)|\d{4}-(?:0[0-9])-
(?:[3][0-1])|\d{4}-(?:1[0-2])-(?:[0-2]\d)|\d{4}-(?:1[0-2])-(?:[3][0-1])','2018-12-31 2018-09-02 2018-02-29 2018-10-31 qwhowq3056-13-24 2018-01-32')
print(lst)
# 三、匹配qq號 5-12 首字符沒有0
import re
qqnum = input("請輸入您的qq號:")
lst = re.findall('^[1-9]\d{4,11}$',qqnum)
if len(lst) == 0:
print("您輸入的qq號格式有錯誤")
else:
print("您的qq號爲:",lst[0])
# 四、11位的電話號碼
import re
call_num = input("請輸入您的電話號碼:")
lst = re.findall("^[1-9]\d{10}$",call_num)
if len(lst) == 0:
print("您輸入的手機號有誤")
else:
print("您輸入的電話號碼是:",lst[0])
# 五、長度爲8-10位的用戶密碼 : 包含數字字母下劃線
import re
lst = re.findall('[\da-zA-Z_]{8,10}','js_28aAA')
print(lst)
# 6 寫出4位驗證碼的正則匹配
import re
lst = re.findall('[\da-zA-Z]{4}','fF4n 1231 312313 dads12 123 d a ddd')
print(lst)
# 7、匹配郵箱地址 郵箱規則
# @以前必須有內容且只能是字母(大小寫)、數字、下劃線(_)、減號(-)、點(.)
# @和最後一個點(.)之間必須有內容且只能是字母(大小寫)、數字、點(.)、減號(-),且兩個點不能挨着
# 最後一個點(.)以後必須有內容且內容只能是字母(大小寫)、數字且長度爲大於等於2個字節,小於等於6個字節
import re
lst = re.findall(r'[a-zA-Z\d\-\_\.]+@[a-zA-Z\d\.\-]+\.[a-zA-Z]{2,6}','1.9_05697@q.3q.com 1.9_05697@q.3q.com1234 9.j05697@q-.q.com6789')
print(lst)
import re
# 八、從相似
# <a>wahaha</a>
# <b>banana</b>
# <h1>qqxing</h1>
# <h1>q</h1>
# 這樣的字符串中,
# 1)匹配出 wahaha,banana,qqxing 內容。
"<h1>(.*?)<h1>"
"""
import re
strvar = "<h1>qqxing</h1> <b>banana</b>"
lst = re.findall("<.*?>(.*?)<.*?>",strvar)
print(lst)
re.search("<.*?>(.*?)<.*?>",strvar)
"""
import re
strvar= """<a>wahaha</a> <b>banana</b> <h1>qqxing</h1> <h1>q</h1>
"""
lst1 = re.findall(r"<.*?>([^<>]{2,})<.*?>",strvar)
print(lst1)
# 2)匹配出 a,b,h1這樣的內容
lst2 = re.findall(r"</(.*?)>",strvar)
print(lst2)
lst3 = re.findall(r"<([^/]*?)>",strvar)
print(lst3)
# 9.
print("========把字符串進行運算==========")
strvar = "5*6-7/3"
def suan(strvar):
strvar = strvar
lst = re.findall("(?:\d+)(?:[*/+-])(?:\d+)", strvar)
for i in lst :
obj = re.search("(\d+)([*/+-])(\d+)",i)
#res = obj.group()
#print(res)
if obj.group(2) == "*":
res = int(obj.group(1)) * int(obj.group(3))
#print(res)
elif obj.group(2) == "/":
res = int(obj.group(1)) / int(obj.group(3))
#print(res)
elif obj.group() == "+":
res = int(obj.group(1)) + int(obj.group(3))
#print(res)
elif obj.group(2) == "-":
res = int(obj.group(1)) - int(obj.group(3))
#print(res)
strvar = strvar.replace(i,str(res))
return strvar
strvar = suan(strvar)
print("=====1========")
print(strvar)
strvar = suan(strvar)
print("=====2========")
print(strvar)
# 10.計算器
import re#計算乘除的方法def parse_exp(exp): if "*" in exp: a,b = exp.split("*") #print(a,b) return str(float(a) * float(b)) if "/" in exp: a,b = exp.split("/") return str(float(a) / float(b))#去除++ +- -- -+ bug 狀況def exp_format(exp): #若是出現下面狀況就替換相應的 exp = exp.replace("+-","-") exp = exp.replace("--","+") exp = exp.replace("-+","-") exp = exp.replace("++","+") return exp#實際計算def exp_calc(strvar): #計算乘除 while True: res_obj = re.search("\d+(\.\d+)?[*/][+-]?\d+(\.\d+)?",strvar) if res_obj: res = res_obj.group() #print(res) #5*-2 res2 = parse_exp(res) #print(res) strvar = strvar.replace(res,res2) else: break #print(strvar) #計算加減 res = exp_format(strvar) #print(lst) lst = re.findall("[+-]?\d+(?:\.\d+)?",res) #print(lst) count = 0 for i in lst: count += float(i) #print(count) return count#去除括號def remove_bracket(strvar): while True: #匹配出最裏面一層的括號 res_obj = re.search("\([^()]+\)",strvar) if res_obj: res_exp = res_obj.group() #print(res_exp) #計算口號裏面的值,exp_calc res = str(exp_calc(res_exp)) #print(res,type(res)) #把算好的實際數值轉換成字符串,替換之前的圓括號 strvar = strvar.replace(res_exp,res) else: #直接返回替換好的字符串 return strvar#主函數def main(strvar): #先把全部的空格去掉 strvar = strvar.replace(" ","") #去掉空格 res = remove_bracket(strvar) #print(res) #計算最後結果 return exp_calc(res)a = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'res = main(a)print(res)#驗證結果res = eval(a)print(res)