正規表達式 Regular Expression
# 正規表達式 支援的所有元字元:
# . ^ $ * + ? {} [] \ | ()
# . 比對任何一個字元(而不是标點符号) 。多行模式下\n除外。單行模式下.可以比對\n
# \ 轉義符,eg.想精确比對"." 可以"\."
# \b 比對一個位置(同 ^ $),單詞的開始或結束
# \d 比對任何一個十進制數字,相當于[0-9]
# \D 比對任何一個非十進制數字,相當于[^0-9]
# \s 比對任何一個空白字元,相當于[\t\n\r\f\v]
# \S 比對任何一個非空白字元,相當于[^\t\n\r\f\v]
# \w 比對任何一個字母數字字元,相當于[a-zA-Z0-9_]
# \w 比對任何一個非字母數字字元,相當于[^a-zA-Z0-9_]
# [] 比對任何一類字元
# eg.[abcd]将比對 'a' 'b' 'c' 'd' 中的任意一個字元, [.?!] 比對标點符号
# 可加"-"表示範圍, eg.[a-d] 同 [abcd]
# * 重複比對前面一個字元 "0-無窮多" 次(預設比對盡可能長,*? 則比對盡可能短), eg 1*2 可以比對 2 12 112 1112 11112 111112 ...
# + 重複比對前面一個字元 "1-無窮多" 次(預設比對盡可能長,+? 則比對盡可能短), eg 1+2 可以比對 12 112 1112 11112 111112 ...
# ? 重複比對前面一個字元 "0-1" 次(預設比對盡可能長,?? 則比對盡可能短), eg 1?2 可以比對 2 12
# 還有一個作用: ?" 表示接下來比對到 " 之後就不再繼續比對,這對于 "abc"."def" 這種隻想拿到"abc" 的case很有用
# 這對于左右括号,左右引号之類的模式比對很有用
# {} 重複比對前面一個字元 指定範圍 次(預設比對盡可能長,{}? 則比對盡可能短), 算上前一個字元一共
# eg.1{3}2 可以比對 1112, 而 1{3,5}可以比對1112 11112 111112, 1{3,}2 則可以比對 1112 11112 111112 1111112 ...
# eg.\d{8} 可以比對八個數字 -------------------------??? 八個不是九個
# ^ 多行模式下代表一行的起始,相當于是\n之後的那個字元,單行模式下代表整個字元串的開始。 放在[]中相當于取反[^x]
# $ 多行模式下代表一行的末尾,相當于是\n,單行模式下代表整個字元串的結束 eg.比對一行就是 "^.*$" 不過python可以直接用split("\n")
# | 相當于或,任意一個正規表達式比對上就算比對上
# () 分組,告訴 {} 需要重複的target, 比對之後的字串也會按照 組 的方式
# eg.比對一個ip位址 (eg. 192.168.0.1):
# \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
# (\d{1,3}\.){3}\d{1,3} #當擷取了這個字串的時候,('192','168','0','1')會被組織成一個元組
#一個例子:提取存檔的html檔案中所有的網址
# http:// 開頭,或者 https:// 開頭,然後是任意一個字元,(重複任意次),網址一般被""包起來
import re
#1) re.I(re.IGNORECASE): 忽略大小寫
#2) re.M(MULTILINE): 多行模式,改變’^’和’$’的行為
#3) re.S(DOTALL): 點任意比對模式,改變’.’的行為
#4) re.L(LOCALE): 使預定字元類 \w \W \b \B \s \S 取決于目前區域設定
#5) re.U(UNICODE): 使預定字元類 \w \W \b \B \s \S \d \D 取決于unicode定義的字元屬性
#6) re.X(VERBOSE): 詳細模式。這個模式下正規表達式可以是多行,忽略空白字元,并可以加入注釋
p = re.compile('"https?://.*?"', re.IGNORECASE) # ?" 表示找到離前面一個"最近的"之後就不再繼續比對
#p = re.compile('"http://.*?"|"https://.*?"', re.I) # re.IGNORECASE 和 re.I 都表示忽略大小寫
with open("/home/fang/桌面/demo.html") as fr:
doc = fr.read()
print(type(doc))
# findall() 找到所有比對的字串,作為一個list傳回
# search() 掃描字元串,找到RE比對的位置(隻傳回第一個的位置)
# p.match(doc) 會傳回一個match對象(不包含pattern應該傳回None吧)
for i in p.findall(doc):
print (type(i), i)
除了上面 findall函數外,還有幾個常用的:
re.match(pattern, string, flags=0)
或
rp = re.compile(pattern, re.I | re.S)
mobj = rp.match(string) #預設從 pos=0 出開始比對,pos=0除比對不上就認為比對失敗,endpos=len(string)為預設的停止比對位置
rp = re.compile(pattern, re.I | re.S)
mobj = rp.search(string) #search 直接從給定字元串中查找比對的位置,找到就直接傳回不再繼續查找了
rp = re.compile(pattern, re.I | re.S)
res = list(rp.finditer(string)) # 類似 search,不同的是是搜尋全部,傳回一個疊代器,這裡直接轉化為 MatchObject 組成的 list
傳回 MatchObject
拿到 MatchObject(比如是 mobj),你可以:
使用 mobj.group()或 mobj.group(0) 擷取比對的字元串
使用 mobj.group(i)擷取比對字元串中的第i個子group(前提是 pattern 中有"(xx)"),或 mobj.groups() 擷取子group組成的元組
使用 mobj.span() 擷取比對字元串位于原始字元串中的index,即 (start,end),或 單獨使用 mobj.start() mobj.end()
content = "hello , this is a test string"
p = re.compile(r'\w*is', re.I)
for i in p.findall(content):
print(i) # 傳回 this 和 is
for i in range(len(content)):
res = p.match(content,i) # 預設從pos=0開始比對,pos=0處比對不上就認為比對失敗,endpos=len(string)為預設的停止比對位置
if res:
print("found,{},{}".format(res.group(),res.span()))
else:
print("not found at {}".format(i))
res = p.search(content) # search 直接從給定字元串中查找比對的起始位置,找到就傳回不再繼續找了
if res:
print("found,{},{}".format(res.group(),res.span()))
else:
print("not found")
res = list(p.finditer(content)) # 傳回所有比對的位置 span()
print(res)
for i in res:
print("type {}, {}, {}".format(type(i), i, i.span()))
https://deerchao.cn/tutorials/regex/regex.htm
https://blog.csdn.net/m0_38109046/article/details/85070106