Awk

查找其中包含 2 個術語的文本文件(以任何順序,在任何行)

  • April 20, 2020

我一直在查看grep -e您在哪裡進行“與”操作,這是我想要的那種事情。但是,如果我做對了,這兩個術語必須在同一行才能返回。

相反,我感興趣的是在一個目錄中找到我所有的文件,其中包含兩個術語,可能在不同的行上。如果順序很重要,我確實知道一個術語總是會出現在另一個之前,但是當然可以使用通用解決方案。

TL&DR

注意:你必須自己測試哪一個是最快的。

grep -rlzE '(TermOne.*TermTwo)|(TermTwo.*TermOne)'

find . -type f -exec grep -q 'TermOne' {} \; \
              -exec grep -q 'TermTwo' {} \; \
              -print

awk '/TermOne/{if(p==0)p=1; if(p==2)p=3}
    /TermTwo/{if(p==0)p=2; if(p==1)p=3}
    p==3{print FILENAME;p=0;nextfile}' ./*

一個文件

沒有辦法建構一個可以匹配文件中兩個單獨字元串的正則表達式。

可以使用任一交替搜尋兩個術語:

grep -E '(TermOne.*TermTwo)|(TermTwo.*TermOne)' file

或前瞻:

grep -P '(?=.*TermOne)(?=.*TermTwo)' file

但前提是這兩個術語在同一行

-z也可以使用 GNU grep選項使整個文件充當一個文件(如果文件不包含 NUL。Unix 文本文件不包含) :

grep -zE '(TermOne.*TermTwo)|(TermTwo.*TermOne)' file

It is not possible to use -z with -P at the same time, so, no lookahead solutions possible as of today.

The other alternative is to grep twice:

<file grep 'TermOne' | grep -q 'TermTwo'

The exit code of the whole pipe will signal 0 only if both terms were found in one file.

Or, to use awk:

awk '/TermOne/{if(p==0)p=1; if(p==2)p=3}
    /TermTwo/{if(p==0)p=2; if(p==1)p=3}
    p==3{print "both terms found"; exit}' file

list files

The first two solutions from above will work to recursively list all files by adding the options -r (recursive, which then there is no need for a filename) and -l (list matching filenames).

grep -rlzE '(TermOne.*TermTwo)|(TermTwo.*TermOne)'

Or, using find (two grep calls):

find . -type f -exec grep -q 'TermOne' {} \; -exec grep -q 'TermTwo' {} \; -print

Or, using awk (the glob will include only the PWD):

awk '/TermOne/{if(p==0)p=1; if(p==2)p=3}
    /TermTwo/{if(p==0)p=2; if(p==1)p=3}
    p==3{print FILENAME;p=0;nextfile}' ./*

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