shell 将JSON导出到环境变量

rjjhvcjd  于 2023-01-31  发布在  Shell
关注(0)|答案(7)|浏览(242)

如果我有一个这样的JSON,

{
    "hello1": "world1",
    "testk": "testv"
}

而且我想把这些键值对都导出为环境变量,怎么通过shell脚本来实现呢?比如说我在终端上写的时候,echo $hello1world1应该打印出来,其他键值对也是一样的?注:上述JSON存在于名为$values的变量中,而不是文件中。
我知道这将通过jq完成,并为此编写了一个shell脚本,但它不起作用。

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

nom7f22z1#

this answer完成了将JSON转换为key=value对的所有艰苦工作,借用this answer,您可以通过循环jq输出并使用export来将这些值放入环境中:

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

如果正在加载的变量包含嵌入的空格,这也是合理的,只是稍微复杂一些:

while read -rd $'' line
do
    export "$line"
done < <(jq -r <<<"$values" \
         'to_entries|map("\(.key)=\(.value)\u0000")[]')
sbdsn5lh

sbdsn5lh2#

使用命令替换$()

# $(jq -r 'keys[] as $k | "export \($k)=\(.[$k])"' file.json)
# echo $testk
testv
    • 编辑:**回复此评论

你应该做的

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

请注意$values周围的double引号

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

z2acfund3#

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

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

解释:

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

下面是一个输出示例,从AWS记录集中导出json键:
导出“名称”="\052.应用程序. nmanos-群集-一个.devcluster.openshift.com”。
导出“类型”=“A”
导出“旅馆区域ID”=“Z67 SXBLZRQ 7 X7 T”
导出“域名服务器名称”=“a24070461 d50270 e-1391692. us-east-1.
导出“评估目标运行状况”=假

gzjq41n4

gzjq41n44#

现有的答案中没有一个在POSIX shell的值中保留空格,下面的代码行将使用jq获取一些JSON的每个key:value,并将它们导出为环境变量,适当地转义空格和特殊字符。

    • 2023年1月28日漏洞修复更新:**

我之前的答案并不适用于所有可能的值,可能会导致错误。请改为使用下面的行,该行使用jq的@sh字符串来正确地转义shell的值。您还必须将eval之后的所有内容用引号括起来以保留换行符。我更新了示例JSON文件,以包含更多的字符来进行测试。
这个答案现在似乎是唯一一个可以处理所有情况的答案。没有循环,而且只需要一行就可以导出所有值。缺点是它使用eval,这在理论上是危险的......但是因为 * entire * key = value现在被shell转义了,所以使用起来应该是安全的。

    • 新答案(使用此答案):**
eval "export $(echo "$values" \
  | jq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
    • 旧答案(不要使用此答案):**
eval export $(echo "$values" \
  | jq -r 'to_entries|map("\"\(.key)=\(.value|tostring)\"")|.[]' )
    • 编辑**感谢@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

示例脚本:

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

运行示例脚本:

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

优点:

  • 不需要巴什
  • 保留值中的空白
  • 无回路
    • *(update)**正确转义所有值以便在shell中使用

缺点:

  • 使用eval,我非常肯定这不是"安全的"
mpgws1up

mpgws1up5#

以下shell脚本所示的方法避免了特殊字符的大多数(但不是全部)问题:

#!/bin/bash

function json2keyvalue {
   cat<<EOF | jq -r 'to_entries|map("\(.key)\t\(.value|tostring)")[]'
{
    "hello1": "world1",
    "testk": "testv"
}
EOF
}

while IFS=$'\t' read -r key value
do
    export "$key"="$value"
done < <(json2keyvalue)

echo hello1="$hello1"
echo testk="$testk"

请注意,上面假设键本身没有制表符。

h79rfbju

h79rfbju6#

jtc解决方案:

export $(<file.json jtc -w'[:]<>a:<L>k' -qqT'"{L}={}"')
5uzkadbs

5uzkadbs7#

我想出了一个解决方案(在bash中):

function source_json_as_environ() {
  eval "$(jq -r '
  def replace_dot:
    . | gsub("\\."; "_");
  def trim_spaces:
    . | gsub("^[ \t]+|[ \t]+$"; "");
  to_entries|map(
    "export \(.key|trim_spaces|replace_dot)="
    + "\(.value|tostring|trim_spaces|@sh)"
    )|.[]' $@)"
}

你可以这样使用它:

$ source_json_as_environ values.json

相关问题