天天看點

正規表達式 檢索字元串

正規表達式 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

繼續閱讀