ファイルから複数の文字列をgrep'pingします(必ず同じ行にある必要はありません)。

ファイルから複数の文字列をgrep'pingします(必ず同じ行にある必要はありません)。

私はいくつかの文字列を含むファイルをより頻繁に見つけることを認めます。

現在私はそうします:

grep -rl string1 | xargs grep -l string2 | xargs grep -l string3

これを行うためのツールはありますか?

これはまたはgrepです。string1string2string3

grep -rl -e string1 -e string2 -e string3

string1string2and を含むファイルが必要ですstring3が、必ずしも同じ行にある必要はありません。

grepたぶん現代人の一人( )がag/ack/rg/siftこれを行うことができますか?

答え1

次のように使用できますgrep

grep -rzlP '(?s)(?=.*?string1)(?=.*?string2)(?=.*?string3)' .
  • (?s)既知の「dot-all」は次のとおりです。grepドットが.新しい行文字と一致することを許可します。\n

  • (?=.*?pattern):順方向予測は.0回以上出現し、*欲張りのないすべての文字と一致し、その後にパターン(string1、、、string2...)が続きます。

次の関数を作成できます(POSIX bashzsh)。

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 $?

関連情報