私はいくつかの文字列を含むファイルをより頻繁に見つけることを認めます。
現在私はそうします:
grep -rl string1 | xargs grep -l string2 | xargs grep -l string3
これを行うためのツールはありますか?
これはまたはgrep
です。string1
string2
string3
grep -rl -e string1 -e string2 -e string3
string1
string2
and を含むファイルが必要ですstring3
が、必ずしも同じ行にある必要はありません。
grep
たぶん現代人の一人( )がag/ack/rg/sift
これを行うことができますか?
答え1
次のように使用できますgrep
。
grep -rzlP '(?s)(?=.*?string1)(?=.*?string2)(?=.*?string3)' .
(?s)
既知の「dot-all」は次のとおりです。grepドットが.
新しい行文字と一致することを許可します。\n
(?=.*?pattern)
:順方向予測は.
0回以上出現し、*
欲張りのないすべての文字と一致し、その後にパターン(string1
、、、string2
...)が続きます。
次の関数を作成できます(POSIX bash
&zsh
)。
mgrep() { eval grep -rzlP $(printf ''\''(?s)';
printf '(?=.*?'\''"$%d"'\'')' $(eval echo {1..$#}); printf ''\''') . ; }
次に、次のように呼び出すと、現在の作業ディレクトリのすべての内容を含むファイルが再帰的に検索されます。模様存在する。
mgrep string1 string2 string3
grep
また、基本的にサポートされているすべてのタイプのパターンを処理します(grep
必要に応じて機能のオプションを事前に調整してください。)。
mgrep string 'pattern with space' '\d+' [0-9] [...]
答え2
agrep
(オリジナル似たようなgrep
、)のものではありませtre
ん
agrep -ld '$x' 'pattern1;pattern2;pattern3'
一致しない正規表現($x
末尾に続くもの)を区切り文字として使用します。
(ディレクトリ内のすべてのファイルを再帰的に検索するには、find
または再帰的なglobを使用します。)zsh
ただし、パターンは各ファイルのすべての行ではなく、ファイルの内容全体と一致します。
gawk を使用してスクリプトを作成できます。
PATTERNS='pattern1;pattern2;pattern3' gawk -e '
BEGIN{n = split(ENVIRON["PATTERNS"], a, ";")}
BEGINFILE{for (i in a) p[a[i]]; found = 0}
{
for (i in p)
if ($0 ~ i) {
if (++found == n) {print FILENAME; nextfile}
delete p[i]
}
}' -E /dev/null file1 file2...
(遅いですが)。
答え3
αГsнιnの答えによると:
mgrep() {
grep -rzlP "(?s)$(printf "(?=.*?%s)" "$@")" .
}
mgrep string1 string2 string3
答え4
次の提案は簡単ですが、より効果的で強力です。
#!/bin/bash
tab=(one three five)
# grep_all's return status indicates if all patterns have at least
# one matching result in the text file specified as argument.
grep_all()
{
local -n patterns=$1 # allows to refer to an array
local file=$2
# abort if a pattern is not found
for pattern in "${patterns[@]}"; do
if ! grep -q -e "$pattern" "$file"; then
return 1
fi
done
}
grep_all tab file.txt
echo $?