我在shell脚本中使用jq工具(jq-json-processor)来解析json。
我有2个json文件,想要将它们合并为一个独特的文件
这里是文件的内容:
文件1
{
"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
答案 0 :(得分:104)
从1.4开始,现在可以使用*
运算符。给定两个对象时,它将以递归方式合并它们。例如,
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
}
如果您还想摆脱其他键(如预期结果),一种方法是:
jq -s '.[0] * .[1] | {value: .value}' file1 file2
或者可能更有效(因为它不会合并任何其他值):
jq -s '.[0].value * .[1].value | {value: .}' file1 file2
答案 1 :(得分:42)
使用jq -s add
:
$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
"a": 0,
"b": "bar",
"c": "baz"
}
这会将stdin中的所有JSON文本读入数组(jq -s
执行此操作),然后它会减少"它们。
(add
定义为def add: reduce .[] as $x (null; . + $x);
,它迭代输入数组的对象值并添加它们。对象添加==合并。)
答案 2 :(得分:27)
谁知道你是否仍然需要它,但这是解决方案。
一旦进入--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
(注意:如果你想合并内部对象而不是只用正确的文件覆盖左边的文件,你需要手动完成)
答案 3 :(得分:15)
这是一个在任意数量的对象上以递归方式(使用echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)'
{
"A": {
"a": 1,
"b": 2
},
"B": 3
}
)运行的版本:
jQuery('#multiselect').val("");
答案 4 :(得分:5)
首先,{“value”:。value}可以缩写为{value}。
其次,--argfile选项(在jq 1.4和jq 1.5中可用)可能是有意义的,因为它避免了必须使用--slurp选项。
将这两个文件组合在一起,可以按照以下指定的方式组合:
$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'
'-n'标志告诉jq不要从stdin读取,因为输入来自这里的--argfile选项。
答案 5 :(得分:0)
这可用于合并命令上指定的任意数量的文件:
jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json
或针对任意数量的文件
jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json