我有两个文件JSON。 我想两个数组SomeFile2.json的追加到SomeFile1.json如下。
SomeFile1.json
[
{
"DNSName": "CLB-test-112a877451.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0886ed703de64028a"
}
]
},
{
"DNSName": "CLB-test1-156925981.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0561634c4g3b4fa25"
}
]
}
]
SomeFile2.json
[
{
"InstanceId": "i-0886ed703de64028a",
"State": "InService"
},
{
"InstanceId": "i-0561634c4g3b4fa25",
"State": "InService"
}
]
我想下面的结果:
[
{
"DNSName": "CLB-test-112a877451.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0886ed703de64028a"
"State": "InService"
}
]
},
{
"DNSName": "CLB-test1-156925981.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0561634c4g3b4fa25"
"State": "InService"
}
]
}
]
我在bash shell中通过处理jq
。 但是,未果。
因为我发现JQ相当困难,我开始在一个程序的方法:使用Ruby的JSON模块:
ruby -rjson -e '
states = JSON.parse(File.read(ARGV.shift)).map {|o| [o["InstanceId"], o["State"]]}.to_h
data = JSON.parse(File.read(ARGV.shift))
data.each do |obj|
obj["Instances"].each do |instance|
instance["State"] = states[instance["InstanceId"]] || "unknown"
end
end
puts JSON.pretty_generate data
' SomeFile2.json SomeFile1.json
但是,我们希望JQ,所以一些试验和错误,并在手册中找到此之后: https://stedolan.github.io/jq/manual/#Complexassignments - (注意,我改变了状态的实例之一,所以我可以验证输出更好)
$ cat SomeFile2.json
[
{
"InstanceId": "i-0886ed703de64028a",
"State": "InService"
},
{
"InstanceId": "i-0561634c4g3b4fa25",
"State": "NOTInService"
}
]
首先,提取状态到对象映射ID的状态:
$ state_map=$( jq -c 'map({"key":.InstanceId, "value":.State}) | from_entries' SomeFile2.json )
$ echo "$state_map"
{"i-0886ed703de64028a":"InService","i-0561634c4g3b4fa25":"NOTInService"}
然后,更新的第一个文件的实例:
jq --argjson states "$state_map" '.[].Instances[] |= . + {"State": ($states[.InstanceId] // "unknown")}' SomeFile1.json
[
{
"DNSName": "CLB-test-112a877451.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0886ed703de64028a",
"State": "InService"
}
]
},
{
"DNSName": "CLB-test1-156925981.ap-northeast-1.elb.amazonaws.com",
"Instances": [
{
"InstanceId": "i-0561634c4g3b4fa25",
"State": "NOTInService"
}
]
}
]
由于第二个文件的内容显然意在从INSTANCEID定义映射到国家,让我们假设到JQ的以下调用启动:
jq --argfile dict SomeFile2.json -f program.jq SomeFile1.json
接下来,让我们创建一个合适的解释:
reduce $dict[] as $x ({}; . + ($x|{(.InstanceId): .State}))) as $d
现在剩下的就是容易:
map(.Instances |= map(. + {State: $d[.InstanceId]}))
把拼在一起的program.jq:
(reduce $dict[] as $x ({}; . + ($x|{(.InstanceId): .State}))) as $d
| map(.Instances |= map(. + {State: $d[.InstanceId]}))
备择方案
字典如上可以在不使用被构造reduce
,如下所示:
($dict | map( {(.InstanceId): .State}) | add) as $d
另一种替代方法是使用INDEX/2
:
(INDEX($dict[]; .InstanceId) | map_values(.State))) as $d
如果您的JQ没有INDEX/2
,你可以从它的SNARF高清https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq