スクリプトで、テキストを含むファイルを検索したいのですが、テキストが見つかったファイルと、テキストが見つかったファイル内の全行を知る必要があります。 はgrep
これを行うユーティリティですが、ファイル名にテキストが含まれている場合、出力を使用可能な形式にするにはどうすればよいでしょうか。コマンドによくあるような、使用できる:
何らかの--porcelain
モードはありますか。grep
git
test-num:1:date:jan-2
例: grep で調べたい名前のファイルがいっぱい入ったフォルダーがあります。ファイルには、FAILURE:<some reason>
またはSUCCESS:<some reason>
(他にもいろいろ) が含まれています。特定の理由を検索し、ファイル名と理由 (テキストの行全体でもかまいません) を後で処理するために保存するスクリプトが必要です。出力は、コードを実行できる限り、どのようなデータ構造でもかまいません。
答え1
というものは存在しません。grep --porcelain
ファイル名の特殊文字の処理は、UNIX では常に後付けでした。効率を犠牲にして、次のような方法を試すことができます。
pattern='some pattern'
for file in ./*; do
grep -- "$pattern" "$file" | while read -r line; do
printf 'file: %s, line: %s\n' "$file" "$line"
done
done
答え2
-Z
GNU grep の最近のバージョンには、出力を明瞭にするオプションがありますが、これは主に のような用途を対象grep -lZ … | xargs -0
としています。行の内容をリストする場合、コロンがヌルバイトに置き換えられ、行の内容は依然として改行で終わる¹ ため、これはまだ機能しますが、シェルはヌルバイトの処理が得意ではないため、この出力を解析するのは困難です。
1 つの簡単な解決策 (パフォーマンスは若干低下しますが) は、各ファイルに対して grep を個別に実行することです。
別の解決策としては、Perl や Python などの言語を使用することです。Perl は grep をエミュレートするのに非常に優れています。 grep REGEX
基本的には ですperl -ne '/REGEXP/ and print'
。
しかし、出力が実際には曖昧でない場合は、これはまったく必要ないかもしれません。たとえば、一致する行にコロンが含まれていない場合、ファイル名は最後のコロンまでの行のすべてになります。一致する行がすべてSUCCESS
orで始まりFAILURE
、これらの単語がファイル名に表示されない場合は、これを使用して区切りなどを特定できます。
¹改行で終了するレコードではなく、ヌルで終了するレコードをフィルター処理する場合を除き、ヌルはファイル名のターミネータと結果のターミネータの両方になります。出力がなくても、ファイル名と出力内の一致するレコードが交互に出力レコードとして表示されるため、出力は依然として明確です。-z
-o
答え3
grepの出力を安全に使用する方法スクリプトでは?
...出力はどんな形式でも構いませんデータ構造、コードを実行できる限りは。
シェルスクリプトには実際にはデータ構造がありません。配列はありますが、それだけです。また、パイプ出力を安全に配列に取り込むのは簡単ではありません。(ファイル名できる改行を含みます。
最善の方法はコードを実行するシェル スクリプトでファイルを実行する場合は、ファイルに対してコードを実行するだけで、後で使用するためにファイル名を保存しないでください。
これを行うには、次を使用しますfind
。
find somedir -type f -exec grep -q somepattern {} \; -exec somecommand {} \;
しかし、あなたの質問をよく読むと、あなたは実際にはコードを実行するファイル全体にわたって、特定の行に対してテキスト処理を実行したいだけです。この場合、おそらく GNU Grep オプションが-z
適しています。これと、Sed または Awk の知識があれば、質問に対処できます。
ファイルの命名規則を変更するのが賢明かもしれません。