如何或為什麼使用 .*?
比 .*
更好?
我在 SuperUser 上回答了這個問題,該問題與 grepping 輸出時使用的正則表達式類型有關。
我給出的答案是這樣的:
tail -f log | grep "some_string.*some_string"
然後,在對我的回答的三條評論中,@Bob寫道:
.*
是貪婪的,可能會擷取比你想要的更多的東西。.*?
通常會更好。那麼這個,
the
?
是 上的修飾符*
,使其變得懶惰而不是貪婪的預設值。假設 PCRE。我用Google搜尋
PCRE
,但在我的答案中無法理解這有什麼意義?最後這個,
我還應該指出,這是正則表達式(grep 預設執行 POSIX 正則表達式),而不是 shell glob。
我只知道 Regex 是什麼以及它在 grep 命令中的基本用法。所以,我無法得到這 3 條評論中的任何一條,我有這些問題:
.*?
vs.的用法有什麼區別.*
?- 哪個更好,在什麼情況下?請提供例子。
也有助於理解評論,如果有人可以
更新:作為問題的答案Regex 與 Shell Globs 有何不同? @Kusalananda在他的評論中提供了這個連結。
注意:如果需要,請在回答參考上下文之前閱讀我對此問題的回答。
Ashok 已經指出了和 之間的區別
.*
,.*?
所以我將提供一些額外的資訊。
grep
(假設是 GNU 版本)支持 4 種匹配字元串的方法:
- 固定字元串,帶有
-F
選項- 基本正則表達式 (BRE),預設
- 擴展正則表達式 (ERE),帶有
-E
選項- Perl 兼容的正則表達式 (PCRE),帶有
-P
GNU grep 中的選項
grep
預設使用 BRE。BRE 和 ERE 記錄在 POSIX 的正則表達式章節中,PCRE 記錄在其官方網站中。請注意,功能和語法可能因實現而異。
值得一提的是,BRE 和 ERE 都不支持惰性:
多個相鄰重複符號(“+”、“*”、“?”和間隔)的行為會產生未定義的結果。
因此,如果您想使用該功能,則需要改用 PCRE:
# PCRE greedy $ grep -P -o 'c.*s' <<< 'can cats eat plants?' can cats eat plants # PCRE lazy $ grep -P -o 'c.*?s' <<< 'can cats eat plants?' can cats
你能解釋一下**
.*
vs.*?
**嗎?
.*
用於匹配可能的“最長” 1模式。.*?
用於匹配可能的“最短” 1模式。根據我的經驗,最想要的行為通常是第二個。
例如,假設我們有以下字元串,我們只想匹配 html 標籤2,而不是它們之間的內容:
<title>My webpage title</title>
現在比較
.*
vs.*?
:# Greedy $ grep -P -o '<.*>' <<< '<title>My webpage title</title>' <title>My webpage title</title> # Lazy $ grep -P -o '<.*?>' <<< '<title>My webpage title</title>' <title> </title>
1.正如 Kusalananda 指出的那樣,正則表達式上下文中“最長”和“最短”的含義有點棘手。有關詳細資訊,請參閱官方文件。
2.不建議用正則解析html。這只是一個用於教育目的的範例,請勿在生產中使用它。
假設我採用如下字元串:
can cats eat plants?
使用貪心
c.*s
將匹配整個字元串,因為它以 開頭c
和結尾s
,作為一個貪心運算符,它將繼續匹配直到最後出現 s。而使用惰性
c.*?s
只會匹配直到s
找到第一次出現,即 stringcan cats
。從上面的範例中,您可能能夠收集到:
“貪婪”意味著匹配最長的可能字元串。“懶惰”意味著匹配最短的可能字元串。將 a 添加到, ,或
?
等量詞後使其變得懶惰。*``+``?``{n,m}