Grep
如何搜尋包含一組單詞的多行文本文件(例如,AAA & (BBB | CCC) & ~DD)?
我需要找到滿足相對複雜條件的文件。例如,我想查找滿足以下所有條件的所有文件:
- 確實包含單詞 AAAA
- 確實包含單詞 BBB 或 CCCCC(可能同時包含它們)
- 不包含單詞 DDD
單詞可以以任何順序出現,也可以出現在不同的行中。
我有一個解決方案,它結合了
find
andegrep
,但不是很清晰。find . \( -type f -and -exec egrep -q 'BBB|CCCCC' {} \; \ -and -exec egrep -q AAAA {} \; \ -and -not -exec egrep -q DDD {} \; \) -print
有沒有更好的方法來解決這個問題?
在我看來,您的解決方案非常適合這項任務。但是,它很慢,因為它為每個文件生成 3 個程序。我認為 Awk 更適合這裡,因為它允許一次性讀取整批文件(ARG_MAX 允許),使用
{} +
而不是{} \;
.GNU awk:
find . -type f -exec gawk ' BEGINFILE{c1=c2=c3=0} /AAA/ {c1=1} /BBB/||/CCC/{c2=1} /DDD/ {c3=1; nextfile} ENDFILE{if(c1 && c2 && !c3)print FILENAME} ' {} +
POSIX *:
find . -type f -exec awk ' FNR==1{ if(NR>1 && c1 && c2 && !c3)print f c1=c2=c3=0 f=FILENAME } /AAA/ {c1=1} /BBB/||/CCC/{c2=1} /DDD/ {c3=1; nextfile} END{if(c1 && c2 && !c3)print f} ' {} +
*實際上,
nextfile
仍然不是 POSIX,但它已被下一期標準接受。您可以將其刪除以符合 POSIX 問題 7;結果將是相同的,但會降低性能。注意:如果 Awk 沒有讀取文件的權限,它就會退出。在 GNU Find 中,只需添加
-readable
標誌即可避免這種情況。如果 GNU Find 不可用,可以使用 Test 作為附加過濾器:find . -type f -exec test -r {} \; -exec awk ' ... ' {} +
但是為每個文件生成一個測試代表了性能損失。
進一步閱讀: