如何用jq中的shell变量替换JSON字典中的值?

mnowg1ta  于 2023-03-03  发布在  Shell
关注(0)|答案(3)|浏览(334)

我有以下JSON结构:

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

和shell中的以下环境变量:

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))'
bhmjp9jg

bhmjp9jg1#

您需要export Bash变量才能被jq看到:

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"
}
8ulbf1ek

8ulbf1ek2#

导出大量shell变量可能不是一个好主意,也不能解决数组值变量的问题。因此,按照将variable = value的细节打印到一个文件中,然后将该文件与模板组合的思路来考虑可能是一个好主意。这很容易做到,互联网上的例子比比皆是,SO上的例子也可能如此。例如,您可以像这样使用printf

printf "%s\t" ${BASH_VERSINFO[@]}
3   2   57  1

您可能还会发现declare -p很有用。
另请参见www.example.comhttps://github.com/stedolan/jq/wiki/Cookbook#arbitrary-strings-as-template-variables

fv2wmkja

fv2wmkja3#

下面是一个替换文件中所有变量的方法,而不管它们的嵌套级别如何。如果它们没有在环境中定义,它会保持它们的值不变。在下面的示例中,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

相关问题