代码之家  ›  专栏  ›  技术社区  ›  Rick Baker

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

  •  0
  • Rick Baker  · 技术社区  · 6 年前

    所以,我尝试导出一个环境变量,它来自一个返回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 回复  |  直到 6 年前
        1
  •  5
  •   Charles Duffy    6 年前

    对于以下所有情况,我假设:

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

    这可以用 eval 但是 只有当你相信你的意见 .

    这可能看起来像:

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

    这个 @sh 内置 jq 将内容转义为 埃瓦 -在巴什很安全, 埃瓦 然后调用确保内容经过所有解析阶段(因此,在由 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
    
        2
  •  0
  •   peak    6 年前

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

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

    如果值可能包含(原始)换行符,则需要 映射文件 使用-d选项,可以使用如下所示:

    $ 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