天天看點

python正則中的貪婪與非貪婪

當重複一個正規表達式時,如用 a*,操作結果是盡可能多地比對模式。當你試着比對一對對稱的定界符,如 HTML 标志中的尖括号。比對單個 HTML 标志的模式不能正常工作,因為 .* 的本質是“貪婪”的

>>> s = '<html><head><title>Title</title>'

>>> len(s)

32

>>> print re.match('<.*>', s).span()

(0, 32)

>>> print re.match('<.*>', s).group()

<html><head><title>Title</title>

RE 在 "<html>" 中 比對 "<",.* 會消耗掉字元串的剩餘部分。RE 中保持更多的向左比對, 不能在字元串結尾比對“>”,是以正規表達式必須一個字元一個字元地回溯,直到它找到 > 的比對。最終的比對從 "<html" 中的 "<" 到 "</title>" 中的 ">",這變成了全文比對,并不是你想要的結果。

在這種情況下,解決方案是使用不貪婪的限定符 *?、+?、?? 或 {m,n}?,盡可能比對小的文本。在上面的例子裡,在第一個 "<" 之後立即嘗試比對 ">",當它失敗時,引擎一次增加一個字元,并在每步重試 比對">"。這個處理将得到正确的結果:

>>> print re.match('<.*?>', s).group()

<html>

注意一下比較:

>>> re.findall(r"a(d+?)", "a23b")

        ['2']

>>> re.findall(r"a(d+)", "a23b")

        ['23']

---------------比較一下兩者的不同------------------------

>>> re.findall(r"a(d+)b", "a23b")

        ['23']

>>> re.findall(r"a(d+?)b", "a23b")

        ['23']

有時使用貪婪模式比對網頁代碼時,會出現卡機情況,比如用這個語句:

sty_scr_tag = re.compile('(<style.*?[^>]*>.*?([Ss]+)</style>)|(<script.*?[^>]*>.*?</script>)|(<script.*?[^>]*>.*?([Ss]+?)</script>)',re.M)

content = sty_scr_tag.sub('', content)

去比對baike.baidu.com這個網頁,你會發現編譯器一直卡在那裡不會動,但當語句變成這個:

sty_scr_tag = re.compile('(<style.*?[^>]*>.*?</style>)|(<script.*?[^>]*>.*?</script>)|(<script.*?[^>]*>.*?([Ss]+?)</script>)',re.M)

content = sty_scr_tag.sub('', content)

時,就可以了

下一篇: 6666666