Shell

如何使用具有管道字元的模式 grep 多個模式?

  • November 6, 2019

我想在幾個文件中找到與兩種模式之一匹配的所有行。我試圖通過鍵入找到我正在尋找的模式

grep (foo|bar) *.txt

但是外殼將其解釋|為管道並在bar不是執行檔時抱怨。

如何在同一組文件中查找多個模式?

首先,您需要保護模式不被外殼擴展。最簡單的方法是在它周圍加上單引號。單引號防止它們之間的任何擴展(包括反斜杠);那麼你唯一不能做的就是在模式中使用單引號。

grep -- 'foo*' *.txt

(還要注意--選項結束標記,以阻止grep包括 GNU 在內的某些實現grep將名為-foo-.txt例如的文件(將由 shell from 擴展*.txt)作為選項(即使它遵循非選項參數)這裡))。

如果確實需要單引號,則可以將其寫為'\''(結束字元串文字、文字引號、打開字元串文字)。

grep -- 'foo*'\''bar' *.txt

其次,grep 至少支持兩種模式語法。舊的預設語法(基本正則表達式)不支持交替 ( |) 運算符,儘管某些版本將其作為副檔名,但使用反斜杠編寫。

grep -- 'foo\|bar' *.txt

可移植的方法是使用更新的語法,擴展正則表達式。您需要將-E選項傳遞給以grep選擇它(以前是使用egrep單獨的命令完成的²)

grep -E -- 'foo|bar' *.txt

當您只是在尋找幾種模式中的任何一種(而不是使用析取建構複雜模式)時,另一種可能性是將多個模式傳遞給grep. 您可以通過在每個模式前面加上-e選項來做到這一點。

grep -e foo -e bar -- *.txt

或者將模式放在多行:

grep -- 'foo
bar' *.txt

或者將這些模式儲存在一個文件中,每行一個並執行

grep -f that-file -- *.txt

請注意,如果*.txt擴展為單個文件,grep則不會像存在多個文件時那樣在匹配的行前面加上其名稱。要解決這個問題,對於grepGNU 等一些實現grep,您可以使用該選項,或者對於任何實現,您可以作為額外參數-H傳遞。/dev/null


¹ 一些grep實現甚至更支持與 perl 兼容的,帶有, 的-P擴展*,*-X用於-Kksh 萬用字元…

² 雖然egrep已被 POSIX 棄用並且有時在某些系統上不再存在,但在未安裝 POSIX 或 GNU 實用程序時,在某些其他系統(如 Solaris)上,這egrep是您唯一的選擇,因為它不/bin/grep支持-e-f、或 multi-線條圖案-E``\|

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