
特定のディレクトリにあるファイルから2つ以上の文字列を検索して行番号を印刷したいと思います。
検索結果にはそのファイルのみを含める必要があります。みんな言及された文字列が存在します(同じ行にある場合もありない場合もあります)。すべての文字列ではなく、一部の文字列を含むファイルを除外する必要があります。
これを達成するための便利なコマンドは何ですか?
答え1
GNU awkを使用すると、次のことができます。
awk 'BEGINFILE { n1=n2=0 }
/str1/ { n1=FNR }
/str2/ { n2=FNR }
ENDFILE { if (n1&&n2) print FILENAME,n1,n2 }
' files...
考慮すべき文字列リストのバリエーション:
awk -v s="str1 str2 str3" '
BEGIN { n=split(s,str) ; m=(2^n)-1 }
BEGINFILE { f=0 }
{ for (i=1; i<=n; i++)
if ($0 ~ str[i]) {
l[i] = FNR
f += 2^(i-1)
}
}
ENDFILE {
if (f==m)
for (i=1; i<=n; i++) print FILENAME,l[i]
}
' files...
これらのコマンドはスクリプトファイルで最もよく実行され、代替リストはパラメータとしてスクリプトに渡されfiles...
ます。"$@"
ディレクトリ(コメントで要求されているように)と検索文字列を渡す "findall"などのスクリプトは次のとおりです。
dir=${1:?}
shift
cd "$dir" || exit 1
awk -v s="$*" '
...as above...
' *
と言えますfindall dir str1 str2 ... strN
。 (検索文字列には空白文字を含めないでください。)
答え2
1 つの方法は、最初に一致するファイルを一覧表示し、ファイルを再度読み、必要な行を検索することです。この方法は、一致ファイルが大きすぎるか多すぎない限り、うまく機能します。
特殊文字を含むファイル名の問題を回避するための最新のGNUユーティリティ(Linux / Cygwin)で十分であるとします。
grep -Rlz -Fe "foo" . |
xargs -0 grep -lz -Fe "bar" /dev/null |
xargs -0 grep -lz -Fe "qux" /dev/null |
xargs -0 awk '/foo|bar|qux/ {print FNR}' /dev/null