【问题标题】:Convert bash array to json array and insert to file using jq将 bash 数组转换为 json 数组并使用 jq 插入文件
【发布时间】:2018-03-09 00:03:06
【问题描述】:

给定一个 bash 数组,如何将其转换为 JSON 数组以便输出到带有 jq 的文件?

另外:有没有办法保持 server_nohup 数组不变,而不是每次都重写整个 json 文件?

newArray=(100 200 300)
jq -n --arg newArray $newArray '{
    client_nohup: [ 
        $newArray
    ],
    server_nohup: [

    ]
}' > $projectDir/.watch.json

当前输出:

{
"client_nohup": [
    "100"
],
"server_nohup": []
}

期望的输出:

{
"client_nohup": [
    100,
    200,
    300
],
"server_nohup": []
}

【问题讨论】:

    标签: arrays json bash edit jq


    【解决方案1】:

    (1) 如果 newArray 中的所有值都作为没有空格的 JSON 值有效,那么您可以将值作为流进行管道传输,例如

    newArray=(100 200 300)
    echo "${newArray[@]}" |
      jq -s '{client_nohup: ., server_nohup: []}'
    

    (2) 现在假设您只想更新文件中的“nohup”对象,比如 nohup.json:

    { "client_nohup": [], "server_nohup": [ "keep me" ] }
    

    由于您使用的是 bash,因此您可以编写:

    echo "${newArray[@]}" |
      jq -s --argjson nohup "$(cat nohup.json)" '
        . as $newArray | $nohup | .client_nohup = $newArray
      '
    

    输出

    (1)

    {
      "client_nohup": [
        100,
        200,
        300
       ],
      "server_nohup": []
    }
    

    (2)

    {
      "client_nohup": [
        100,
        200,
        300
      ],
      "server_nohup": [
        "keep me"
      ]
    }
    

    其他情况

    有志者事竟成 :-)

    例如,请参阅How to format a bash array as a JSON array 上接受的答案(尽管这不是一个完全通用的解决方案)。

    有关通用解决方案,请参阅 jq 常见问题解答中的 ?: How can a variable number of arguments be passed to jq? How can a bash array of values be passed in to jq as a single argument?https://github.com/stedolan/jq/wiki/FAQ

    通用解决方案

    需要明确的是,如果已知数组值是有效的 JSON,那么有几个不错的选择;如果数组值是任意 bash 字符串,那么使用 jq 处理它们的唯一有效、通用的方法是使用 -R jq 选项(例如与 -s 结合使用),但随后将读取 (bash) 字符串作为 JSON 字符串,因此任何预期的类型信息都将丢失。 (这里的重点在于 bash 字符串不能包含 NUL 字符的技术性。)

    通常,为了减轻后一个问题,可以将数字字符串转换为 JSON 数字,例如使用 jq 成语:(tonumber? // .).

    【讨论】:

    • 感谢您的详尽回答,但案例 1 是否需要将键 client_nohup 的值作为嵌套在另一个数组中的数组?
    • 看来我复制并粘贴了错误的输出。固定。
    • 这适用于简单值,但通常会失败,因为数组元素可能包含换行符或其他无效的 JSON 字符。
    • @chepner - 请注意,您的观点已在答案的结尾和最后部分中提出,其中指出了可以在其他情况下应用的技术。
    • FAQ 中的答案对于数组x=(1 $'a\nb' 2) 失败。
    【解决方案2】:

    一般来说,唯一真正安全的方法是多次调用jq,将每个元素添加到前一个命令的输出中。

    arr='[]'  # Empty JSON array
    for x in "${newArray[@]}"; do
      arr=$(jq -n --arg x "$x" --argjson arr "$arr" '$arr + [$x]')
    done
    

    这可确保在将 bash 数组的每个元素 x 添加到 JSON 数组之前对其进行正确编码。

    不过,这很复杂,因为bash 不区分数字和字符串。这会将您的数组编码为["100", "200", "300"],而不是[100, 200, 300]。最后,您需要对数组包含的内容有所了解,并相应地对其进行预处理。

    【讨论】:

    • 并非“唯一真正安全的方法是多次调用 jq”。 jq FAQ 展示了如何使用 NUL 来避免这种情况。在 FAQ 中搜索 NUL github.com/stedolan/jq/wiki/FAQ
    • 使用tonumber? // . 可以解决数字/字符串问题,当然这会将引用的数字转换为数字...
    • @peak 这里的问题不是分隔符,而是 bash 字符串不一定是有效的 JSON 字符串。它被破坏的原因与$'"foo\bar"' 这样的硬编码值不是有效的 JSOn 相同。
    • 正如在别处提到的,您显然忽略了 -R 选项的使用。当然,这会强制所有内容都成为 JSON 字符串,因此您关于在“通用”解决方案中丢失数字和字符串之间的区别的观点是完全有效的。0。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 2018-01-09
    • 1970-01-01
    • 2021-05-13
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多