使用带有jq的bash变量将项目添加到json

时间:2018-07-30 13:42:30

标签: bash jq

我正在尝试使用bash创建一个字符串变量,该变量将在jq中使用,以向json文件添加新元素。但这在转义我的双引号。参见下面的“错误输出”。我期望在“预期输出”下面显示输出。用bash变量向文件名添加更多字段的正确方法是什么?

我的输入json文件(input.json):

'

我的bash脚本:

<a href="#" onclick="$('#element').dialog('open');" ></a>

错误的输出:

{
  "##_Comment1": "Inputs",
  "filename": [
    "file1",
    "file2",
    "file3",
    "file4"
  ]
}

正确的输出:

#!/bin/bash
update_list='"abc","efg"'

cat input.json | jq --arg args "$update_list" '.["filename"] += [$args]'

2 个答案:

答案 0 :(得分:1)

稍微放松一下自己的情况:

$ jq --arg args '"abc","efg"' '.["filename"] += [$args]' <<< '{"filename":[]}'
{
  "filename": [
    "\"abc\",\"efg\""
  ]
}

在这里,我们正在args引擎中有效地将jq分配给字符串:

args = "\"abc\",\"efg\""

如果要将args设置为列表/数组,则需要采取另一种方法。


您可以格式化JSON参数并使用--argjson

$ jq --argjson args '["abc","efg"]' '.["filename"] += $args' <<< '{"filename":[]}'
{
  "filename": [
    "abc",
    "efg"
  ]
}

或者您可以将update_list放入数组并循环:

update_list=()
update_list+=("abc")
update_list+=("efg")

echo '{"filename":[]}' > test

for i in "${update_list[@]}"; do
    jq --arg update_item "${i}" '.["filename"] += [ $update_item ]' < test \
        | sponge test
done
$ cat test
{
  "filename": [
    "abc",
    "efg"
  ]
}

答案 1 :(得分:1)

在原始问题中,update_list是用引号引起来的字符串的逗号分隔列表,如果这些字符串也是JSON字符串,则以下解决方案将起作用:

jq --arg args "$update_list" '
  .["filename"] += ($args|split(",")|map(fromjson))'

update_list变体

如果可以将update_list作为JSON数组使用,那么@Attie的第一个解决方案就是解决之道。

如果update_list是bash数组,则涉及对每个数组元素一次调用jq的解决方案是不必要的(并且可能令人尴尬地)效率低下;建议的解决方案也可能会造成问题,因为更新不是原子的。有更好的选择。例如,jq FAQ提到了一种技术,当将该技术应用于当前问题时,它会产生以下解决方案:

jq --argjson args "$(printf '%s\n' "${update_list[@]}" | jq -nR '[inputs]')" '
 .["filename"] += $args' 

或者出于鲁棒性考虑,可以使用NUL作为分隔符:

jq --argjson args "$(printf '%s\0' "${update_list[@]}" | jq -sR 'split("\u0000")')" '
 .["filename"] += $args'

另请参阅jq convert bash array to json array and insert to file