同じファイルに2つの単語インスタンスが存在するファイルを検索する方法を探しています。これまで、以下を使用して検索を実行してきました。
find . -exec grep -l "FIND ME" {} ;
私が遭遇している問題は、「FIND」と「ME」の間にスペースが1つだけ存在しない場合、検索結果でファイルが生成されないことです。 「FINDME」ではなく「FIND」と「ME」の両方の単語がファイルに存在する以前の検索文字列をどのように適合させるのですか?
AIXを使用しています。
承認された回答:
GNUツールの場合:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
標準的に行うことができます:
find . -type f -exec grep -q FIND {} ; -exec grep -l ME {} ;
ただし、最大2つのgrep
が実行されます。 ■ファイルごと。その数のgrep
の実行を回避するには ■ファイル名に任意の文字を使用できるようにしながら、移植性を維持するには、次のようにすることができます。
convert_to_xargs() {
sed "s/[[:blank:]"']/\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\"
print ""
}
line = $0
}'
END { print line }'
}
export LC_ALL=C
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
find
の出力を変換するというアイデア xargsに適した形式に変換します(空白が必要です(C
のSPC/TAB / NL ロケール、他のロケールのYMMV)一重引用符、二重引用符、円記号で空白などをエスケープできる単語のリストを区切ります。
通常、find -print
の出力を後処理することはできません 、ファイル名を改行文字で区切り、ファイル名に含まれる改行文字をエスケープしないためです。たとえば、次のように表示されます:
./a
./b
b
という1つのファイルかどうかを知る方法がありません a<NL>.
というディレクトリにあります または、2つのファイルの場合a
およびb
現在のディレクトリにあります。
.//.
を使用する 、//
find
によって出力されたファイルパスにそれ以外の場合は表示できません (名前が空で/
のディレクトリなどがないため ファイル名には使用できません)、//
を含む行が表示された場合は 、それが新しいファイル名の最初の行です。したがって、そのawk
を使用できます すべての改行文字をエスケープするコマンド。ただし、それらの行の前にある文字はエスケープします。
上記の例をとると、find
最初のケース(1つのファイル)で出力されます:
.//a
./b
どのawkが脱出するか:
.//a
./b
そのため、xargs
それを1つの引数と見なします。そして2番目のケース(2つのファイル):
.//a
.//b
どのawk
そのままにしておくので、xargs
2つの引数が表示されます。
LC_ALL=C
が必要です だからsed
、awk
(およびxargs
のいくつかの実装 )任意のバイトシーケンスに対して機能し(ユーザーのロケールでは有効な文字を形成しませんが)、空白を単純化します。 SPCとTABのみを定義し、さまざまなユーティリティによるバックスラッシュのエンコードがエンコードに含まれている文字のさまざまな解釈に関する問題を回避します。