複数のANDパターンでgrepを実行する方法は?

複数のANDパターンでgrepを実行する方法は?

暗黙的なマルチパターンマッチングが欲しいそしてモード間は、複数のgrepを順次実行するのと同じです。

grep pattern1 | grep pattern2 | ...

それでは、これを似たようなものに変換する方法は?

grep pattern1 & pattern2 & pattern3

パラメータを動的に構築してすべてが文字列に収まる必要があるため、単一のgrepを使用したいと思います。フィルタの使用は grep ではなくシステム機能であるため、これについての議論ではありません。


この質問を以下と混同しないでください。

grep "pattern1\|pattern2\|..."

これは一つですまたはマルチパターンマッチング。私は〜を探していますそしてパターンマッチング。

答え1

パターンリストの各パターンに一致する行を見つけるにはagrep(元のパターン、今フラッシュ、関連性がないよりもTRE正規表現ライブラリ)は、次の構文を使用して実行できます。

agrep 'pattern1;pattern2'

GNUを使用すると、grepPCREサポートでビルドするときに次のことができます。

grep -P '^(?=.*pattern1)(?=.*pattern2)'

そしてASTgrep:

grep -X '.*pattern1.*&.*pattern2.*'

(sを一致文字列.*として追加して、<x>&<y><x><y> 正確にa&bそのような文字列は一致しないため、絶対一致しません。はい同時にab

パターンが重ならない場合は、次のこともできます。

grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'

最良のポータブル方法はおそらくawk上記のようになります。

awk '/pattern1/ && /pattern2/'

または以下を使用してsed

sed -e '/pattern1/!d' -e '/pattern2/!d'

またはperl:

perl -ne 'print if /pattern1/ && /pattern2/'

これらのすべてには異なる正規表現構文があります。

awk//終了状態のパターンに一致する行があるかどうかを反映しません。以下を行うには:sedperl

awk '/pattern1/ && /pattern2/ {print; found = 1}
     END {exit !found}'
perl -ne 'if (/pattern1/ && /pattern2/) {print; $found = 1}
          END {exit !$found}'

またはコマンドをgrep '^'

zgrep潜在的にgzipで圧縮されたファイルの場合、通常はシェルスクリプトラッパーインを使用し、上記grepのソリューションのいずれかを使用するか(その実装を使用できないため、grepast-openソリューションではありません)、モジュールを使用できます。入力時にファイルを透明に解凍します。grepzgrepPerlIO::gzipperl

perl -MPerlIO::gzip -Mopen='IN,gzip(autopop)' -ne '
  print "$ARGV:$_" if /pattern1/ && /pattern2/' -- *.gz

zgrep(ファイルが十分に小さい場合は、各ファイルに対して実行せずに内部で解凍を実行するよりも少なくとも効率的ですgunzip。)

答え2

重要なgrepバージョンを指定していません。一部の正規表現エンジンは、「&」を使用してANDを介して複数の一致を許可しますが、これは非標準で移植できない機能です。ただし、少なくともGNU grepはこれをサポートしていません。

OTOH、grepをsed、awk、perlなどで簡単に置き換えることができます(重みが増える順にリストされています)。 awkを使用すると、コマンドは次のようになります。

awk '/regexp1/ && /regexp2/ && /regexp3/ {印刷}'

そして、簡単な方法でコマンドラインで指定するように設定できます。

答え3

git grep

使用される構文は次のとおりです。git grep複数のパターンを組み合わせて使用ブール値表現:

git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3

上記のコマンドは、すべてのパターンに一致する行を一度に印刷します。

--no-indexGitで管理されていないファイルを現在のディレクトリから取得します。

助けを確認してくださいman git-grep

また見なさい:

~のためまたはタスクを参照してください。

答え4

patterns各行にパターンが含まれている場合は、次のことができます。

awk 'NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1' patterns -

または、正規表現の代わりに部分文字列と一致します。

awk 'NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1' patterns -

noneを印刷するのではなく空の場合は、すべての入力行を印刷するには、またはinにpatterns置き換えます。NR==FNRFILENAME==ARGV[1]ARGIND==1gawk

これらの関数は、パラメータで指定された各文字列を部分文字列として含む行をSTDINに出力します。gagrep allを表し、大文字とgai小文字を無視します。

ga(){ awk 'FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1' <(printf %s\\n "$@") -; }
gai(){ awk 'FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1' <(printf %s\\n "$@") -; }

関連情報