使用jq导出带有空格的环境变量

时间:2018-07-23 15:10:33

标签: bash environment-variables jq

因此,我正在尝试导出来自返回json值的api的环境变量。想要使用jq只做一个衬板,但是如果值中有空格,我将无法使其工作

尝试不使用引号引起来的值

/app/src $ $(echo '{"params":[{ "Name":"KEY","Value":"value with space"}]}' | jq
 -r '.params[] | "export " + .Name + "=" + .Value')
/app/src $ printenv KEY
value
/app/src $ 

接下来,我尝试将值包装在引号中

/app/src $ $(echo '{"params":[{ "Name":"KEY","Value":"value with space"}]}' | jq
 -r '.params[] | "export " + .Name + "=\"" + .Value + "\""')
sh: export: space": bad variable name
/app/src $ 

2 个答案:

答案 0 :(得分:5)

对于以下所有内容,我假设:

json='{"params":[{ "Name":"KEY","Value":"value with space"}]}'

可以使用eval完成,但是仅当您信任自己的输入

这看起来像:

eval "$(jq -r '.params[] | "export \(.Name | @sh)=\(.Value | @sh)"' <<<"$json")"

内置于@sh中的jq使内容在bash中逃逸为eval安全,然后调用eval确保内容经过所有解析阶段(因此jq发出的数据中的文字引号成为句法)。


更好的形式是生成一个以NUL分隔的键/值列表...

build_kv_nsv() {
  jq -j '.params[] |
    ((.Name | gsub("\u0000"; "")),
     "\u0000",
     (.Value | gsub("\u0000"; "")),
     "\u0000")'
}

...然后填充一个关联数组...

declare -A content_received=( )
while IFS= read -r -d '' name && IFS= read -r -d '' value; do
  content_received[$name]=$value
done < <(build_kv_nsv <<<"$json")

# print the value of the populated associative array
declare -p content_received

...或使用带有前缀以确保安全的命名空间。

while IFS= read -r -d '' name && IFS= read -r -d '' value; do
  printf -v "received_$name" %s "$value" && export "received_$name"
done < <(build_kv_nsv <<<"$json")

# print names and values of our variables that start with received_
declare -p "${!received_@}" >&2

答案 1 :(得分:0)

如果已知值不包含(原始)换行符,并且您有权访问mapfile,则可能值得考虑使用它,例如

$ json='{"params":[{ "Name":"KEY","Value":"value with space"}]}'
$ mapfile -t KEY < <( jq -r '.params[] | .Value' <<< "$json" )
$ echo N=${#KEY[@]}
N=1

如果值可能包含(原始)换行符,那么您需要使用带有-d选项的mapfile版本,该版本可以如下使用:

$ json='{"params":[{ "Name":"KEY1","Value":"value with space"}, { "Name":"KEY2","Value":"value with \n newline"}]}'
$ mapfile -d $'\0' KEY < <( jq -r -j '.params[] | .Value + "\u0000"' <<< "$json" )
$ echo N=${#KEY[@]}
N=2