たとえば、patterns.txt
あるファイル内にそれらのパターンがすべて存在するかどうかを確認したいとします。
次のようなことができます:
for pattern in $(cat patterns.txt); do
if ! grep -q "$pattern" file.txt; then
echo "Error: missing pattern $pattern"
fi
done
echo "All patterns found"
しかし、これは各パターンを再スキャンする必要があるため非効率的ですfile.txt
(また、ファイルではなく、たとえば大きな可能性があるパイプからのストリーム内のパターンを検索する場合はそれほど単純ではありません)。
grep
(または他のツールで)確認する方法はありますか?全てパターンは存在しますか?
答え1
cat file.txt | awk '
NR == FNR {seen[$0] = 0; next}
{for (p in seen) if ($0 ~ p) seen[p]++}
END {
for (p in seen)
if (seen[p] == 0) {
missing++
print "missing pattern", p
}
if (missing == 0) print "all found"
exit missing
}
' patterns.txt -
cat
コマンドを、テキストを生成するパイプラインに置き換えます。
答え2
これはうまくいくかもしれません:
sort -u patterns.txt > sorted_patterns.txt # only once
diff -sq <(grep -o -f sorted_patterns.txt file.txt | sort -u) sorted_patterns.txt
パターンではなく固定文字列がある場合は、 を使用します-F
。これにより、grep
処理速度が大幅に向上します。
あなたは出来るまた使用するcmp
の代わりに を使用しますdiff -s
。少し速くなるかもしれませんが、何が欠けているかを表示することはできません。
すべてのパターンが見つからなかった場合は出力します。
Files /dev/fd/63 and /dev/fd/62 differ
またはすべてのパターンが見つかった場合:
Files /dev/fd/63 and /dev/fd/62 are identical
-q
知るために残す何不足している。
2a3
> missing_word
答え3
grep
PCRE 拡張機能とコマンドの機能を使用すると、printf
次のようになります。
<infile grep -qzP "(?s)$(printf "(?=.*?%s)" $(<pattern.txt))" &&
echo 'all matched' ||
echo 'one or more pattern(s) does not found'
すべてのパターン(任意の順序)が入力ファイルに見つかりましたインファイルテキストall matched
出力されます。それ以外の場合はテキストone or more pattern(s) does not found
エコーします。
これは、パターンを一致パターンとして機能させ、& ;pat[01]
の両方に一致させ、正確なパターンに一致させるには、文字通りに制御修飾子をからに変更し、特殊文字をエスケープします。pat0
pat1
pat[01]
printf
%s
%q
<infile grep -qzP "(?s)$(printf "(?=.*?%q)" $(<pattern.txt))" &&
echo 'all matched' ||
echo 'one or more pattern(s) does not found'