简体   繁体   English

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

[英]exporting environment variables with spaces using jq

So, I'm trying to export an environment variable that comes from an api that returns json values. 因此,我正在尝试导出来自返回json值的api的环境变量。 Would like to use jq to just do a one liner, but if the values have spaces I cannot get it working 想要使用jq只做一个衬板,但是如果值中有空格,我将无法使其正常工作

Trying without surrounding the value in quotes 尝试不用引号引起来的值

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

Next, I try wrapping the value in quotes 接下来,我尝试将值包装在引号中

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

For all of the below, I'm assuming that: 对于以下所有内容,我假设是:

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

It can be done with eval , but ONLY IF YOU TRUST YOUR INPUT . 可以用eval来完成,但前提是您信任自己的输入

This might look like: 可能看起来像:

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

The @sh builtin in jq escapes content to be eval -safe in bash, and the eval invocation then ensures that the content goes through all parsing stages (so literal quotes in the data emitted by jq become syntactic). jq内置的@sh在bash @sh内容转义为eval -safe,然后eval调用可确保内容经过所有解析阶段(因此jq发出的数据中的文字引号变为语法)。


Better form is to generate a NUL-delimited key/value list... 更好的形式是生成NUL分隔的键/值列表...

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

...and either populate an associative array... ...然后填充关联数组...

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

...or to use a namespace that's prefixed to guarantee safety. ...或使用前缀以确保安全的名称空间。

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

If the values are known not to contain (raw) newlines, and if you have access to mapfile , it may be worthwhile considering using it, eg 如果已知值不包含(原始)换行符,并且您有权访问mapfile ,则值得考虑使用它,例如

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

If the values might contain (raw) newlines, then you'd need a version of mapfile with the -d option, which could be used as illustrated below: 如果这些值可能包含(原始)换行符,那么您需要一个带有-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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM