Grep

如何搜尋包含一組單詞的多行文本文件(例如,AAA & (BBB | CCC) & ~DD)?

  • July 19, 2021

我需要找到滿足相對複雜條件的文件。例如,我想查找滿足以下所有條件的所有文件:

  • 確實包含單詞 AAAA
  • 確實包含單詞 BBB 或 CCCCC(可能同時包含它們)
  • 不包含單詞 DDD

單詞可以以任何順序出現,也可以出現在不同的行中。

我有一個解決方案,它結合了findand egrep,但不是很清晰。

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 '
   ...
' {} +

但是為每個文件生成一個測試代表了性能損失。


進一步閱讀:

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