Regular-Expression

如何或為什麼使用 .*?.* 更好?

  • April 14, 2021

在 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),帶有-PGNU 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找到第一次出現,即 string can cats

從上面的範例中,您可能能夠收集到:

“貪婪”意味著匹配最長的可能字元串。“懶惰”意味著匹配最短的可能字元串。將 a 添加到, ,或?等量詞後使其變得懶惰。*``+``?``{n,m}

引用自:https://unix.stackexchange.com/questions/441927