如何将JSON字典中的值替换为jq中各自的shell变量



我有以下JSON结构:

{
"host1": "$PROJECT1",
"host2": "$PROJECT2",
"host3" : "xyz",
"host4" : "$PROJECT4"
}

以及外壳中的以下环境变量:

PROJECT1="randomtext1"
PROJECT2="randomtext2"
PROJECT4="randomtext3"

我想检查每个键的值,如果它们有一个"$"字符,用它们各自的环境变量(已经存在于shell中(替换它们,以便用正确的环境变量呈现我的JSON模板。

我可以使用jq的--args选项,但在我想要呈现的实际JSON模板中有很多变量。

我一直在尝试以下内容:

jq 'with_entries(.values as v | env.$v)

基本上将每个值作为一个变量,然后用env对象中的变量更新其值,但我似乎错过了一些理解。有没有一种简单的方法可以做到这一点?

编辑

多亏了这个问题的答案,我得以实现我的更大目标,其中一部分问题被问到

  • 迭代对象中的每个值
  • 检查其值,
    • 如果它是一个字符串并且以字符"开头$">
      • 使用该值使用同名的环境变量对其进行更新
    • 如果是一个数组
      • 使用该值检索同名的环境变量
      • 用"作为分隔符,返回字符串数组
      • 使用字符串数组更新值

jq 'with_entries(.value |= (if (type=="array") then (env[.[0][1:]] | split(",")) elif (type=="string" and startswith("$")) then (env[.[1:]]) else  . end))'

您需要exportjq:要查看的Bash变量

export PROJECT1="randomtext1"
export PROJECT2="randomtext2"
export PROJECT4="randomtext3"

然后你可以使用:

jq -n 'with_entries((.value | select(startswith("$"))) |= env[.[1:]])'

并得到:

{
"host1": "randomtext1",
"host2": "randomtext2",
"host3": "xyz",
"host4": "randomtext3"
}
导出大量shell变量可能不是一个好主意,也不能解决数组值变量的问题。因此,最好考虑将变量=值的详细信息打印到文件中,然后将该文件与模板组合。这很容易做到,互联网上的例子比比皆是,可能在SO上也有。例如,您可以像这样使用printf
printf "%st" ${BASH_VERSINFO[@]}
3   2   57  1   

您可能还会发现declare -p很有帮助。

另请参阅https://github.com/stedolan/jq/wiki/Cookbook#arbitrary-字符串作为模板变量

这里有一个方法,它可以替换文件中的所有变量,而不管它们的嵌套级别如何。如果没有在环境中定义值,它会保持这些值的原样。在以下示例中,STREET未定义为环境变量,因此保持不变。

匹配的正则表达式(^\$[A-Z_-]+$(可以根据您的需要进行更改,例如用${}或{{}}定义的变量。

$ cat test.json
{
"name": "$NAME",
"address": [{
"street": "$STREET",
"other": "$not_matching"
}]
}
$ cat test.json | NAME=Joe jq 'walk( if type == "string" and test("^\$[A-Z_-]+$") then . |= env[.[1:]] // . else . end )'
{
"name": "Joe",
"address": [
{
"street": "$STREET",
"other": "$not_matching"
}
]
}

唯一的限制是它只替换完全匹配的值。对于https://$HOSTNAME/index.html这样的值,它将不起作用。为此,请改用sed

最新更新