使用JQ动态修改bash脚本中的JSON文件-使用heredocs或键分配? [英] Dynamically modify JSON file in bash script with jq - use heredocs or key assignments?

查看:21
本文介绍了使用JQ动态修改bash脚本中的JSON文件-使用heredocs或键分配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的JSON文件的一部分,JSON文件本身更长。

{
    "anomalyDetection": {
        "loadingTimeThresholds": {
            "enabled": false,
            "thresholds": []
        },
        "outageHandling": {
            "globalOutage": true,
            "localOutage": true,
            "localOutagePolicy": {
                "affectedLocations": 1,
                "consecutiveRuns": 2
            }
        }
    }
}

这里我需要用提供的参数修改affectedLocationsconsecutiveRuns值,将修改后的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 3modify_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"

注意事项

  1. 如果可能的话,编写设置全局变量(如$template)的函数通常是不可取的。通过定义函数(template),我们也只引入一个名称,而不是为函数引入一个名称,为变量引入一个名称。

  2. 似乎参数update_affectedLocationsupdate_consecutiveRuns应该是数字,因此使用--argjson是有意义的,特别是在考虑到一些弹性和简单性的情况下。

  3. JQ程序通过自由使用更新赋值运算符实现了干燥(即避免了不必要的重复)。

  4. 在JQ程序的行首使用";|";可以轻松实现一定程度的视觉优雅,同时突出逻辑。

还请注意,建议的脚本相当简洁和简单,同时相当健壮。

有些人不建议使用关键字function来定义外壳函数,但它确实使查找函数定义变得非常简单,无论是对于人眼还是对于键盘上的人手指。

这篇关于使用JQ动态修改bash脚本中的JSON文件-使用heredocs或键分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆