シェルスクリプトで jq tools(jq-json-processor)を使用してjsonを解析しています。
2つのjsonファイルがあり、1つの一意のファイルにマージしたい
ここにファイルの内容:
file1
{
"value1": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value1": "v1",
"value2": "v2"
},
"bbb": {
"value1": "v1",
"value2": "v2"
},
"ccc": {
"value1": "v1",
"value2": "v2"
}
}
}
file2
{
"status": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value3": "v3",
"value4": 4
},
"bbb": {
"value3": "v3"
},
"ddd": {
"value3": "v3",
"value4": 4
}
}
}
期待される結果
{
"value": {
"aaa": {
"value1": "v1",
"value2": "v2",
"value3": "v3",
"value4": 4
},
"bbb": {
"value1": "v1",
"value2": "v2",
"value3": "v3"
},
"ccc": {
"value1": "v1",
"value2": "v2"
},
"ddd": {
"value3": "v3",
"value4": 4
}
}
}
私は多くの組み合わせを試みますが、私が得る唯一の結果は以下であり、これは期待される結果ではありません:
{
"ccc": {
"value2": "v2",
"value1": "v1"
},
"bbb": {
"value2": "v2",
"value1": "v1"
},
"aaa": {
"value2": "v2",
"value1": "v1"
}
}
{
"ddd": {
"value4": 4,
"value3": "v3"
},
"bbb": {
"value3": "v3"
},
"aaa": {
"value4": 4,
"value3": "v3"
}
}
このコマンドの使用:
jq -s '.[].value' file1 file2
1.4以降、これは*
演算子で可能になりました。 2つのオブジェクトを指定すると、それらを再帰的にマージします。例えば、
jq -s '.[0] * .[1]' file1 file2
あなたを取得します:
{
"value1": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value1": "v1",
"value2": "v2",
"value3": "v3",
"value4": 4
},
"bbb": {
"value1": "v1",
"value2": "v2",
"value3": "v3"
},
"ccc": {
"value1": "v1",
"value2": "v2"
},
"ddd": {
"value3": "v3",
"value4": 4
}
},
"status": 200
}
他のキー(予想される結果など)も削除したい場合、これを行う1つの方法は次のとおりです。
jq -s '.[0] * .[1] | {value: .value}' file1 file2
または、おそらく多少効率的です(他の値をマージしないため):
jq -s '.[0].value * .[1].value | {value: .}' file1 file2
jq -s add
を使用:
$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
"a": 0,
"b": "bar",
"c": "baz"
}
これにより、すべてのJSONテキストが標準入力から配列に読み込まれ(jq -s
が実行します)、それらが「削減」されます。
(add
はdef add: reduce .[] as $x (null; . + $x);
として定義され、入力配列/オブジェクトの値を反復処理して追加します。オブジェクトの追加==マージ。)
まだ必要かどうかは誰にもわかりませんが、ここに解決策があります。
--Slurp
オプションに到達したら、それは簡単です!
--Slurp/-s:
Instead of running the filter for each JSON object in the input,
read the entire input stream into a large array and run the filter just once.
その後、+
演算子はあなたが望むことをします:
jq -s '.[0] + .[1]' config.json config-user.json
(注:左側のファイルを右側のファイルで上書きするのではなく、内部オブジェクトをマージする場合は、手動で行う必要があります)
これは、任意の数のオブジェクトで(*
を使用して)再帰的に動作するバージョンです。
echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --Slurp 'reduce .[] as $item ({}; . * $item)'
{
"A": {
"a": 1,
"b": 2
},
"B": 3
}
まず、{"value":.value}は{value}に短縮できます。
次に、-argfileオプション(jq 1.4およびjq 1.5で使用可能)は、-Slurpオプションを使用する必要がないため、興味深い場合があります。
これらをまとめると、2つのファイル内の2つのオブジェクトは、次のように指定された方法で結合できます。
$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'
「-n」フラグは、入力がここの--argfileオプションから来るため、jqにstdinから読み取らないように指示します。