スクリプトでgrepの出力をどのように安全に使用できますか?

スクリプトでgrepの出力をどのように安全に使用できますか?

スクリプトでいくつかのテキストを含むファイルを見つけたいです。テキスト付きファイルとテキスト付きファイルの完全な行を知る必要があります。grepこれを行うユーティリティですが、可能であれば出力を:ファイル名から利用可能な形式に変換するにはどうすればよいですか?コマンドでよく使うように使用できる--porcelainパターンはありますか?grepgit

test-num:1:date:jan-2例:grepしたいファイルでいっぱいのフォルダがあります。このファイルには、FAILURE:<some reason>またはSUCCESS:<some reason>(何よりも)が含まれています。特定の原因を検索して後で処理するには、ファイル名と原因(テキスト全体の行が可能)を格納するスクリプトが必要です。出力は、コードを実行できる限り、任意の種類のデータ構造にすることができます。

答え1

grep --porcelainUNIXでは、ファイル名の特殊文字を処理することは必ずしも後で考慮されるわけではありません。次のように試してみることができますが、効率が低下します。

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

最新(-ish)バージョンのGNU grepには出力を明確にするオプションがありますが、-Zほとんどはgrep -lZ … | xargs -0。それでも動作しますが、シェルはヌルバイトを処理するのにうまくいかないため、この出力を解析するのが困難になります。

わずかなパフォーマンスが低下する簡単な解決策は、各ファイルに対して個別にgrepを実行することです。

別の解決策は、PerlやPythonなどの言語を使用することです。 Perlはgrep REGEX基本的にgrepシミュレーションに非常に精通しています  perl -ne '/REGEXP/ and print'

しかし、出力が実際にあいまいでない場合、おそらくこれはまったく必要ありません。たとえば、一致する行にコロンがない場合、ファイル名は行から最後のコロンまでのすべてのエントリです。一致する行がすべてまたはSUCCESSで始まり、FAILUREその単語がファイル名に表示されない場合は、それを使用して区切り記号などを見つけることができます。

1行折り返すレコードの代わりにNullで終わるレコードをフィルタリングするために使用されない限り、nullはファイル名ターミネータと結果ターミネータです。出力はまだ明確ではなく、代替出力レコードはファイル名と出力の一致レコードです。-z-o

答え3

grepの出力を安全に使用する方法台本から?

...出力はどんなタイプでも可能です。データ構造、コードを実行できる限りです。

シェルスクリプトには実際にはデータ構造がありません。配列がありますが、それはすべてです。出力を配列に安全にパイプすることは容易ではありません。 (ファイル名できる改行文字を含みます。 )

最良の方法はコードの実行シェルスクリプトでファイルを操作する方法は、後で使用するためにファイル名を保存するのではなく、ファイルに対してコードを実行することです。

これを行うには、以下を使用してくださいfind

find somedir -type f -exec grep -q somepattern {} \; -exec somecommand {} \;

しかし、あなたの質問をもっと読むと、実際には望まないようです。コードの実行ファイル内の特定の行の一部のテキスト処理のみを実行しようとしています。この場合、GNU Grepオプションが-z望むものかもしれません。 Sed や Awk に関する知識とともに問題を解決できます。


ファイル命名規則を変更するのが賢明かもしれません。

関連情報