JSONログファイルがありますtest.log
。
{"type":"1","fname":"AAA","lname":"bbb" }
{"type":"2","state":"gujarat" }
{"type":"3","city":"ahmedabad" }
{"type":"3","city":"rajkot" }
{"type":"1","fname":"ccc","lname":"ddd" }
次のコマンドを実行します。
cat test.log | jq -c "select(.type==\"1\")|{fname:.fname}" > type_1.txt
cat test.log | jq -c "select(.type==\"3\")|{city:.city}" > type_3.txt
単一のコマンドでjq
複数の出力ファイルを生成できますか?
ファイルに対してjq
コマンドを一度だけ実行しtest.log
、プロジェクトタイプごとに1つの出力ファイルを生成したいと思います。
答え1
~によるとマニュアルのIO部分バージョン1.5以降、jqは標準出力にのみ書き込むことができ、デバッグメッセージをstderr
。
jqを何度も実行したくない場合test.log
(たとえば、大容量ファイルであるため)、次のようにすることができます。
jq -c '(select(.type=="1") | {fname:.fname}), (select(.type=="3") | {city:.city})' test.log > temp
# The file 'temp' contains one entry per line.
grep '^{"fname"' temp > type_1.txt
grep '^{"city"' temp > type_3.txt
rm temp
答え2
を使用する代わりに、jq
他のJSON対応プロセッサであるMiller(mlr
)を使用してください。
mlr --json put -q '
$type == 1 { emit >"type_1.txt", { "fname": $fname } }
$type == 3 { emit >"type_3.txt", { "city": $city } }' file
isの場合、fname
キーとファイルに対応する値を含むJSONオブジェクトを印刷し、そのキーのエントリも処理します。type_1.txt
type
1
type
3
city
ファイルtype_1.txt
がtype_3.txt
存在する場合、このコマンドは新しいデータを書き込む前に切り捨てられます(空になります)。
例を実行してください:
$ mlr --json put -q '$type == 1 { emit >"type_1.txt", { "fname": $fname } }; $type == 3 { emit >"type_3.txt", { "city": $city } }' file
$ cat type_1.txt
{ "fname": "AAA" }
{ "fname": "ccc" }
$ cat type_3.txt
{ "city": "ahmedabad" }
{ "city": "rajkot" }
答え3
jq
stdout(またはstderr)のみが記録されるため、ストリームを別のログファイルに分割するには別のプログラムが必要です。
まずjs
@nwk のコマンドとしてログファイルフィールドの強化を使用します。
jq -c '(select(.type=="1") | {"logfile":.type},{fname:.fname}),
(select(.type=="3") | {"logfile":.type},{city:.city})' test.log
この出力をパイプで接続すると、awk
ファイル名を取得できます。
jq -c '(select(.type=="1") | {"logfile":.type},{fname:.fname}),
(select(.type=="3") | {"logfile":.type},{city:.city})' test.log |
awk -F"\"" 'BEGIN {FPAT="[^{}:\"]+" }
$1=="logfile" {lf="type_"$2".txt"; next}
{print >> lf}'
答え4
パーティーに少し遅れました。この問題を完全に元に戻すことができます。スクリプトで実行したときに他のファイルに書き込む方法を尋ねる代わりに、別のファイルに書き込む出力をjq
生成できます。jq
例は次のとおりです。
jq -r \
$' recurse( .children[] ) |
select( (.type="comment") and (.text != null) ) |
"echo \'" + .text + "\' >> " + .author + ".txt" ' < file.json
実行すると、次のような出力が生成されます。
echo '<p>Nice! Definitely let me know.</p>' >> user_1.txt
echo '<p>I agree.</p>' >> user_2.txt
その後、この出力をスクリプトとして実行して別々のファイルを生成できます。jq
現在、シェル以外の依存関係もなく、パイプもなく、追加のツールも必要ありません。$'
プレフィックスと'
サフィックスはステートメント\'
内でエスケープできますecho
。