我有一个很大的 json 文件,我将该文件的两个部分放在下面。
[
{
"description": null,
"icmp-options": null,
"is-stateless": false,
"protocol": "17",
"source": "1.0.0.0/8",
"source-type": "CIDR_BLOCK",
"tcp-options": null,
"udp-options": {
"destination-port-range": null,
"source-port-range": {
"max": 1433,
"min": 521
}
}
},
{
"description": null,
"icmp-options": null,
"is-stateless": false,
"protocol": "17",
"source": "1.0.0.0/8",
"source-type": "CIDR_BLOCK",
"tcp-options": null,
"udp-options": {
"destination-port-range": null,
"source-port-range": {
"max": 1899,
"min": 1435
}
}
}
]
我想更改目标端口范围值,如下所示
"destination-port-range": {
"max": 100,
"min": 90
},
由于 json 文件非常大,有人可以帮助我如何使用 jq 或任何其他方法来完成此操作?
答案1
使用 JSON 处理工具jq
添加从命令行获取的min
和值:max
jq --argjson min 90 --argjson max 100 \
'map(."udp-options"."destination-port-range" = $ARGS.named)' file
通过使用--argjson
这样的选项,我们创建一个内部变量$ARGS
,其named
键是对象{"min":90,"max":100}
。我正在使用--argjson
而不是--arg
因为后者会将值导入为字符串。
该表达式."udp-options"."destination-port-range" = $ARGS.named
将此对象分配给 的destinaton-port-range
子对象udp-options
,并且我们将map()
其应用于输入中的所有数组元素。键名必须用引号引起来,因为它们包含破折号。
考虑到问题中的数据,结果将相当于:
[
{
"description": null,
"icmp-options": null,
"is-stateless": false,
"protocol": "17",
"source": "1.0.0.0/8",
"source-type": "CIDR_BLOCK",
"tcp-options": null,
"udp-options": {
"destination-port-range": { "max": 100, "min": 90 },
"source-port-range": { "max": 1433, "min": 521 }
}
},
{
"description": null,
"icmp-options": null,
"is-stateless": false,
"protocol": "17",
"source": "1.0.0.0/8",
"source-type": "CIDR_BLOCK",
"tcp-options": null,
"udp-options": {
"destination-port-range": { "max": 100, "min": 90 },
"source-port-range": { "max": 1899, "min": 1435 }
}
}
]
如果您只想在没有预先存在的非空(或非假)值的情况下更新该值,请改用以下表达式:
map(."udp-options"."destination-port-range" |= (. // $ARGS.named))
这会将值更新为与当前值相同,除非它是错误的或者无效的,在这种情况下使用新数据。
答案2
与 sed:
sed '/^\s*"destination-port-range": null,/s/null,/{\n"max": 100,\n"min": 90\n},/' data_file