perl 非貪婪的數量詞

2022-09-06 12:00:27 字數 1518 閱讀 9931

例子:假設在fred and barney went bowling last night 上使用/fred.+barney/進行匹配。我們知道正規表示式

將匹配上,下面我們具體的講解這乙個過程:首先,子模式fred 將匹配其對應的字串。模式的下一部分是.+,它將匹配除了換行符之外的任意字元,次數大於等於一。但,由於加號(+)是貪婪的;它將盡可能的進行匹配。因此,它將匹配剩餘的所有字串,包括night。

現在對banrey 進行匹配,但不能成功,因為已經到了字串的結尾處。由於.+在少乙個字元的情況下仍能匹配成功,因此它退回字串最後乙個字母t。(它雖是貪婪的,但更希望整個模式能匹配成功。)子模式barney 又嘗試匹配,結果仍是不行。因此.+再退回字母h,又進行匹配。乙個字元接乙個字元,.+退回其匹配的字元,直到其退回了字串barney。最後,子模式banrey 被匹配上了,現在整個模式都匹配上了。

如本例所顯示的那樣,這些操作引起了大量的回退操作,因為這些數量詞匹配了太多的字串。

因此對於每乙個貪婪的數量詞,需要一種非貪婪的方法。不是使用加號(+),而是使用非貪婪的數量詞+?,它將匹配一次或多次(加號的意思),但其匹配盡可能少的次數,而非盡可能多的次數。現在我們來看看模式為/fred.+?barney/時的過程:

首先,fred 將被匹配上。接著,模式的下一部分是.+?,它匹配的字元個數不大於1,因此匹配fred 後面的空格。下乙個子模式是banrey,它在這裡不能被匹配(因為現在的位置是and barney… 的開頭)。.+?再匹配a,剩下的模式繼續進行匹配。又一次,barney 不能匹配上,因此.+?再匹配n,依次類推。當.+?匹配了這5 個字元後,barney 可以被匹配上了,現在模式匹配成功。

這裡也存在一些回退操作,但由於引擎只需回退,並只嘗試幾次,其在速度上會有很大提高。但,這種提高依賴於banrey在fred 的附近能被找到。如果資料中fred 在字串的開頭,而barney 在結尾處,則貪婪數量詞方法的速度更快。因此,正規表示式的速度依賴於具體的資料。

非貪婪數量詞不僅和效率相關。即便它和其對應的貪婪數量詞表示式均能匹配(或者不能匹配)同乙個字串,它們匹配的部分也可能是不同的。例如,假設你有一些html 型別的文字,你想移除標記和,而保留其間的內容。下面是文字:

i』am talking about the cartoon with fred and wilma!

下面是一種移除標記的方法。它有什麼錯誤呢?

s#(.*)#$1#g;

其問題出在星號是貪婪的。如果文字變成了下面的樣子,會得到什麼結果?

i thought you said fred and velma, not wilma

此時,模式將匹配從第乙個到最後乙個之間的內容,中間的部分被保留下來。噢!我們需要非貪婪的數量詞。星號的非貪婪的型別是*?,因此此模式應當是:

$#(.*?)#$1#g;

現在它能正確執行了。

由於加號的非貪婪型別是+?,星號的為*?,你可能已經意識到剩下的兩種數量詞其對應的型別也是類似的。花括號的非貪婪型別看起來一樣,只是在閉花括號後有乙個問號,如?或者?。甚至問號數量詞也有非貪婪型別:??。它匹配一次或者0 次,但傾向於匹配0 次。

正規表示式中數量詞的貪婪和非貪婪

在使用各種數量詞時,正規表示式總是匹配盡可能多的復合規則的字元,知道允許匹配的上限。例如,在使用表示式 bo 匹配 booooo 時,會得到匹配結果 booooo 而不是匹配 bo 例如,在使用表示式 bo 匹配 booooo 時,會先匹配 booooo 發現不匹配,則去掉末尾的 o 匹配 booo...

關於正規表示式數量詞的貪婪與非貪婪模式

在匹配正則的時候或許會遇到返回的結果多幾個字元或者少幾個字元,什麼原因呢,這個就是正則的貪婪與非貪婪模式,假設,我的匹配字元是 a asdf444adfadf adfsadf 正規表示式的貪婪模式 a z 列印結果 asdf adfadf adfsad 按原理來說在匹配到第二個字元的時候條件就已經滿...

正規表示式的數量詞

greedy 數量詞x?x,一次或一次也沒有x x,零次或多次x x,一次或多次 xx,恰好 n 次 xx,至少 n 次 xx,至少 n 次,但是不超過m 次 reluctant 數量詞x?x,一次或一次也沒有x x,零次或多次x x,一次或多次x?x,恰好 n 次x?x,至少 n 次x?x,至少 ...