使用JQ动态修改bash脚本中的JSON文件-使用heredocs或键分配? [英] Dynamically modify JSON file in bash script with jq - use heredocs or key assignments?
问题描述
下面是我的JSON文件的一部分,JSON文件本身更长。
{
"anomalyDetection": {
"loadingTimeThresholds": {
"enabled": false,
"thresholds": []
},
"outageHandling": {
"globalOutage": true,
"localOutage": true,
"localOutagePolicy": {
"affectedLocations": 1,
"consecutiveRuns": 2
}
}
}
}
这里我需要用提供的参数修改affectedLocations
和consecutiveRuns
值,将修改后的JSON赋给一个变量,然后在API调用期间使用该变量。
我使用bash创建了两个不同的解决方案来完成上述任务。
选项1-使用heredocs
# Assign the template file to a template var
get_template() {
read -r -d '' template <<JSONTEMPLATE
{
"anomalyDetection": {
"loadingTimeThresholds": {
"enabled": false,
"thresholds": []
},
"outageHandling": {
"globalOutage": true,
"localOutage": true,
"localOutagePolicy": {
"affectedLocations": 1,
"consecutiveRuns": 2
}
}
}
}
JSONTEMPLATE
}
modify_json_with_heredoc() {
# Call the template var assignment
get_template
read -r -d '' json_keys_updated <<JSONSTRING
{
"globalOutage": true,
"localOutage": true,
"localOutagePolicy": {
"affectedLocations": ${1:-1},
"consecutiveRuns": ${2:-2}
}
}
JSONSTRING
# Replace key values from the template with the updated parameters
updated_JSON=$(jq --argjson update_outageHandling "$json_keys_updated"
'.anomalyDetection.outageHandling|=$update_outageHandling'
<<<"$template")
}
选项2-直接修改JSON中的密钥
modify_json_with_vars() {
# Call the template assignment
get_template
updated_JSON=$(jq --argjson update_affectedLocations "${1:-1}" --argjson update_consecutiveRuns "${2:-2}"
' .anomalyDetection.outageHandling.globalOutage|=true
| .anomalyDetection.outageHandling.localOutagePolicy.affectedLocations|=$update_affectedLocations
| .anomalyDetection.outageHandling.localOutagePolicy.consecutiveRuns|=$update_consecutiveRuns'
<<<"$template")
}
我需要能够调用带/不带参数的函数。如果在没有参数的情况下调用函数,则需要保留键的默认值,这就是${1:-1}
${2:-2}
存在的原因。
modify_json_with_vars 2 3
或modify_json_with_heredoc
。我的问题是,以上哪一种做法更好、更快、更安全,也更"正确"。
正如我已经提到的,模板文件更大。目前我只需要修改对象.anomalyDetection.outageHandling.localOutagePolicy
中的键,但是,将来我可能还需要更改其他键,并且需要一个可伸缩和可维护的解决方案。
我认为第一个选项更简洁,因为调用JQ时只有一个参数。但是,如果我需要在整个源模板JSON文件中更改键,那么第二种选择可能更具伸缩性。
欢迎提出建议。
推荐答案
出于下面列出的原因,我也建议使用不同的方法。
#!/usr/bin/env bash
function template {
cat<<EOF
{
"anomalyDetection": {
"loadingTimeThresholds": {
"enabled": false,
"thresholds": []
},
"outageHandling": {
"globalOutage": true,
"localOutage": true,
"localOutagePolicy": {
"affectedLocations": 1,
"consecutiveRuns": 2
}
}
}
}
EOF
}
function modify_json() {
template |
jq --argjson update_affectedLocations "${1:-1}"
--argjson update_consecutiveRuns "${2:-2}" '
.anomalyDetection.outageHandling.localOutagePolicy
|= (.affectedLocations |= $update_affectedLocations
| .consecutiveRuns |= $update_consecutiveRuns )
'
}
updated_JSON=$(modify_json 42 666)
echo "$updated_JSON"
注意事项
如果可能的话,编写设置全局变量(如
$template
)的函数通常是不可取的。通过定义函数(template
),我们也只引入一个名称,而不是为函数引入一个名称,为变量引入一个名称。似乎参数
update_affectedLocations
和update_consecutiveRuns
应该是数字,因此使用--argjson是有意义的,特别是在考虑到一些弹性和简单性的情况下。JQ程序通过自由使用更新赋值运算符实现了干燥(即避免了不必要的重复)。
在JQ程序的行首使用";|";可以轻松实现一定程度的视觉优雅,同时突出逻辑。
还请注意,建议的脚本相当简洁和简单,同时相当健壮。
有些人不建议使用关键字function
来定义外壳函数,但它确实使查找函数定义变得非常简单,无论是对于人眼还是对于键盘上的人手指。
这篇关于使用JQ动态修改bash脚本中的JSON文件-使用heredocs或键分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!