パターン間で暗黙的な[〜#〜] and [〜#〜]を使用してマルチパターンマッチを取得します。つまり、シーケンスで複数のgrepsを実行するのと同じです。
grep pattern1 | grep pattern2 | ...
それをどのように変換するのですか?
grep pattern1 & pattern2 & pattern3
動的に引数を作成するため、単一のgrepを使用したいので、すべてが1つの文字列に収まる必要があります。フィルターの使用はシステム機能であり、grepではないため、引数ではありません
この質問を以下と混同しないでください。
grep "pattern1\|pattern2\|..."
これは[〜#〜] or [〜#〜]マルチパターンマッチです。
agrep
は次の構文で実行できます。
agrep 'pattern1;pattern2'
GNU grep
を使用すると、PCREサポートを使用してビルドすると、次のことができます。
grep -P '^(?=.*pattern1)(?=.*pattern2)'
ast grep
の場合:
grep -X '.*pattern1.*&.*pattern2.*'
(.*
を<x>&<y>
として追加すると、<x>
と<y>
の両方に一致する文字列に一致しますexactly、a&b
は、a
とb
の両方を同時にbeできる文字列がないため、決して一致しません時間)。
パターンが重ならない場合は、次のことも可能です。
grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
すでに述べたように、最も移植性のある方法はおそらくawk
を使用することです。
awk '/pattern1/ && /pattern2/'
sed
の場合:
sed -e '/pattern1/!d' -e '/pattern2/!d'
これらはすべて異なる正規表現構文を持つことに注意してください。
あなたはgrepバージョンを指定しませんでした、これは重要です。一部の正規表現エンジンでは、「&」を使用してANDでグループ化された複数の一致が許可されますが、これは非標準で移植性のない機能です。しかし、少なくともGNU grepはこれをサポートしていません。
OTOHでは、grepをsed、awk、Perlなどに簡単に置き換えることができます(重量の増加順にリストされています)。 awkでは、コマンドは次のようになります。
awk '/ regexp1/&&/regexp2/&&/regexp3/{print; } '
そしてそれは簡単な方法でコマンドラインで指定するように構築することができます。
これはあまり良い解決策ではありませんが、ややクールな「トリック」を示しています
function chained-grep {
local pattern="$1"
if [[ -z "$pattern" ]]; then
cat
return
fi
shift
grep -- "$pattern" | chained-grep "$@"
}
cat something | chained-grep all patterns must match order but matter dont
patterns
に1行に1つのパターンが含まれている場合、次のようなことができます:
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 -
patterns
が空の場合に入力行がない代わりにすべて印刷するには、NR==FNR
をFILENAME==ARGV[1]
に、またはgawk
のARGIND==1
に置き換えます。 。
これらの関数は、引数として指定された各文字列を部分文字列として含むSTDINの行を出力します。 ga
はgrep 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 "$@") -; }
これが私の見解であり、これは複数行の単語に対して機能します。
使用する find . -type f
の後に-exec grep -q 'first_Word' {} \;
と最後のキーワード-exec grep -l 'nth_Word' {} \;
-q
静か/静か-l
一致するファイルを表示
次の例では、「rabbit」と「hole」という単語を含むファイル名のリストを返します。find . -type f -exec grep -q 'rabbit' {} \; -exec grep -l 'hole' {} \;
ripgrep
rg
を使用した例を次に示します。
rg -N '(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)' file.txt
Rustの正規表現エンジン の上に構築されているため、これは最も高速なgreppingツールの1つです。
GH-875 の関連する機能リクエストも参照してください。
このシェルコマンドが役立つことがあります。
eval "</dev/stdin $(printf "|grep '%s'" pattern1 pattern2)" FILE
ただし、すべてのパターンがファイルに格納されている方が簡単なので、次のエイリアスを定義できます。
alias grep-all="cat $(xargs printf '| grep "%s"' < patterns.txt)"
そしてそれを次のように使用します:
cat text.txt | grep-all
もちろん、必要な構文に応じてエイリアスを変更することができるため、次のエイリアスを使用します。
alias grep-all="</dev/stdin $(xargs printf '|grep "%s"' < patterns.txt)"
1つのコマンドだけを使用できます。
grep-all text.txt
その他のアイデアについては、次も確認してください: ファイルのすべてのパターンを一度に一致させます 。
ファイルごとのAND演算については、 ファイルに複数の文字列または正規表現がすべて存在するかどうかを確認してください 。