将JSON导出到环境变量

Qir*_*han 12 bash shell json environment-variables jq

如果我有这样的JSON,

{
    "hello1": "world1",
    "testk": "testv"
}
Run Code Online (Sandbox Code Playgroud)

我想将这些键值对中的每一个导出为环境变量,如何通过shell脚本来实现?那么,例如,当我在终端上写字时echo $hello1,world1应该打印并且类似地用于其他键值对?注意:上面的JSON存在于一个被调用但$values不在文件中的变量中.

我知道它将通过jq并为此编写一个shell脚本来完成,但它不起作用.

for row in $(echo "${values}" | jq -r '.[]'); do
    -jq() {
        echo ${row} | jq -r ${1}
    }
    echo $(_jq '.samplekey')
done
Run Code Online (Sandbox Code Playgroud)

编辑:尝试Turn的答案,我这样做了:

values='{"hello1":"world1","hello1.world1.abc1":"hello2.world2.abc2","testk":"testv"}'
for s in $(echo $values | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" ); do
    export $s
done
Run Code Online (Sandbox Code Playgroud)

Tur*_*urn 14

借用这个将JSON转换为key = value对的所有艰苦工作的答案,您可以通过循环jq输出并将export它们放入环境中来实现:

for s in $(echo $values | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" ); do
    export $s
done
Run Code Online (Sandbox Code Playgroud)

  • 你不需要`for`循环。`export` 可以接受多个参数,因此您可以执行以下操作: `export $(echo $values | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[ ]")` (3认同)
  • @Qirohchan 为什么不试试看呢? (2认同)

sjs*_*sam 8

使用命令替换$()

# $(jq -r 'keys[] as $k | "export \($k)=\(.[$k])"' file.json)
# echo $testk
testv
Run Code Online (Sandbox Code Playgroud)

编辑:回应评论

你应该做

$( echo "$values" | jq -r 'keys[] as $k | "export \($k)=\(.[$k])"' )
Run Code Online (Sandbox Code Playgroud)

请注意double周围的引号$values

注意:无法确认这种方法是否存在安全隐患,即用户是否可以操纵json来造成严重破坏。


Noa*_*nos 7

另一种不使用jq 的方法是使用grep & sed解析json :

for keyval in $(grep -E '": [^\{]' my.json | sed -e 's/: /=/' -e "s/\(\,\)$//"); do
    echo "export $keyval"
    eval export $keyval
done
Run Code Online (Sandbox Code Playgroud)

解释:

  • 首先,grep 将过滤所有"key" : value对(值可以是 "string"numberboolean)。
  • 然后, sed 将替换:=,并删除尾随的,
  • 最后,"key"=value用 eval导出

这是一个输出示例,从 AWS 记录集中导出 json 密钥:

导出“名称”="\052.apps.nmanos-cluster-a.devcluster.openshift.com。"

导出“类型”=“A”

导出“HostedZoneId”=“Z67SXBLZRQ7X7T”

导出 "DNSName"="a24070461d50270e-1391692.us-east-1.elb.amazonaws.com。"

导出“EvaluateTargetHealth”=false


Pet*_*ter 5

现有的答案都没有在 POSIX shell 的值中保留空格。以下行将用于jq获取某些 JSON 的每个键:值并将它们导出为环境变量,并正确转义空格和特殊字符。

2023-01-28:修正更新:

我之前的答案并不适用于所有可能的值,并且可能会导致错误。请改用以下行,它使用 jq 的@sh格式字符串来正确转义 shell 的值。您还必须将后面的所有内容括eval在引号中以保留换行符。我已更新示例 JSON 文件以包含更多用于测试的字符。

现在看来,这个答案是唯一可以处理所有情况的答案。没有循环,只需一行即可导出所有值。缺点是它使用eval,这在理论上是危险的......但是因为整个key=value 现在正在为 shell 进行转义,所以这应该可以安全使用。

新答案(使用这个):

eval "export $(echo "$values" | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
Run Code Online (Sandbox Code Playgroud)

旧答案(不要使用这个):

eval export $(echo "$values" \
  | jq -r 'to_entries|map("\"\(.key)=\(.value|tostring)\"")|.[]' )
Run Code Online (Sandbox Code Playgroud)

编辑感谢@Delthas 指出缺少的“导出”

JSON 文件示例:

bash-5.2$ cat <<'EOJSON' > foo.json
{
 "foo_1": "bar 1",
 "foo_2": "This ! is ' some @ weird $text { to ( escape \" here",
 "foo_3": "this is some \nsample new line\n    text to\ntry and escape"
}
EOJSON
Run Code Online (Sandbox Code Playgroud)

示例脚本:

bash-5.2$ cat <<'EOSH' > foo.sh
values="`cat foo.json`"
eval "export $(echo "$values" | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
export
echo "foo_2: $foo_2"
echo "foo_3: $foo_3"
EOSH
Run Code Online (Sandbox Code Playgroud)

运行示例脚本:

bash-5.2$ env -i sh foo.sh
export PWD='/path/to/my/home'
export SHLVL='1'
export foo_1='bar 1'
export foo_2='This ! is '"'"' some @ weird $text { to ( escape " here'
export foo_3='this is some 
sample new line
    text to
try and escape'
foo_2: This ! is ' some @ weird $text { to ( escape " here
foo_3: this is some 
sample new line
    text to
try and escape
Run Code Online (Sandbox Code Playgroud)

优点:

  • 不需要 Bash
  • 保留值中的空格
  • 无循环
  • (更新)正确转义所有值以便在 shell 中使用

缺点:

  • 使用eval,这被认为是“不安全的”。但是,由于jq转义所有输入,这不太可能导致安全问题(除非jq发现存在无法使用@sh过滤器正确转义数据的错误)。