Python之字符串正則匹配


需求:

正則表達式匹配某個文本模式,但是它找到的是模式的最長可能匹配(因為是貪婪匹配 )。 而你想修改它變成查找最短的可能匹配。
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']
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM