需求:
正則表達式匹配某個文本模式,但是它找到的是模式的最長可能匹配(因為是貪婪匹配 )。 而你想修改它變成查找最短的可能匹配。
import re text2 = 'Computer says "no." Phone says "yes."' str_pat=re.compile(r'"(.*)"') # 匹配引號包裹的任意文本,並編譯 print(str_pat.findall(text2)) #['no." Phone says "yes.'],並不是我們想要的['no.', 'yes.'],由於正則表達式* 匹配0到人一多次,是貪婪匹配 # 解決方式 new_str_pat=re.compile(r'"(.*?)"') print(new_str_pat.findall(text2)) # ['no.', 'yes.']
多行匹配模式
comment = re.compile(r'/\*(.*?)\*/') text1 = '/* this is a comment */' text2 = '''/* this is a multiline comment */ ''' print(comment.findall(text1)) # [' this is a comment '] # [' this is a comment '] print(comment.findall(text2)) # [] new_comment=re.compile(r'/\*((?:.|\n)*?)\*/') # (?:) 指定非捕獲組 不捕獲匹配的文本,也不給此組分配組號。 print(new_comment.findall(text2)) # [' this is a\nmultiline comment '] 定義了一個僅僅用來做匹配,而不能通過單獨捕獲或者編號的組)。
補充:捕獲組和非捕獲組
捕獲組
什么是捕獲呢?使用小括號指定一個子表達式后,匹配這個子表達式的文本(即匹配的內容)可以在表達式或者其他過程中接着用,
怎么用呢?至少應該有個指針啥的引用它吧? 對!默認情況下,每個分組(小括號)會自動擁有一個組號,從左到右,以分組的左括號為標志,第一個出現的分組組號為1,后續遞增。如果出現嵌套,
(\d+)/(\d+)/(\d+) # group1 group2 group3 取捕獲組的值
(?:)(?=)(?<=)非捕獲組
非捕獲組舉例子:
# (?:)非捕獲組 a = "6000¥ 和 1000$" # 需求是得到金額和貨幣種類 # 捕獲組 print(re.findall(r"(\d+)+([$¥])",a)) # [('6000', '¥'), ('1000', '$')] a = "10010.86¥" # 需求是得到金額和貨幣種類,提煉出 10010 和 ¥ # (?:)非捕獲組(),可以理解為只分組而不捕獲 print(re.findall(r"(\d+)(?:\.?)(?:\d+)([¥$])$",a)) # [('10010', '¥') # 非捕獲 (?=)和(?<=) 前后查找,有的資料把它們叫做肯定式向前查找和肯定式向后查找; b="12332aa438aaf" print(re.findall(r"[0-9a-z]{2}(?=aa)",b)) #['32', '38'] 該正則的意思是 匹配這么一個字符串,它要滿足:是兩位字符(數字,或字母),且后面緊跟着兩個a # 分析:44aa 這個子串滿足這個條件,所以可以匹配到,又因為 (?=) 的部分是不捕獲的,所以輸出的只是 44,不包括aa,后面的同理 # 再深入看一下: # 當str第一次匹配成功輸出 32 后,程序要繼續向后查找是否還有匹配的其它子串。那么這時應該從 32aa 的后一位開始向后查找,還是從 32 的后一位呢? # 也就是從索引 5 開始還是從 7 開始呢?有人可能想到是從 32aa 的下一位開始往后找, # 因為 32aa 匹配了正則,所以下一位當然是它的后面也就是從 4 開始。但實際上是從 32 的后一位也就是第一個 a 開始往后找。原因還是 (?=) 是非捕獲的 # 下面說一下 (?<=) 向前匹配 print(re.findall(r"(?<=aa)[0-9a-z]{2}",b)) # ['43']