将JSON数组中的一个字段解析为bash数组


13

我有一个JSON输出,其中包含存储在变量中的对象列表。(我可能没有这样说的权利)

[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

我需要数组中的item2的所有值,以便bash脚本在ubuntu 14.04.1。上运行。

我发现了很多方法可以将整个结果放入数组,而不仅仅是我需要的项目

Answers:


17

使用

$ cat json
[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

码:

arr=( $(jq -r '.[].item2' json) )
printf '%s\n' "${arr[@]}"

输出:

value2
value2_2

是否可以通过变量而不是文件来执行此操作?如果不需要,我会尽量避免过多的文件系统访问。一旦我拉这个数组,我就完成了json输出。
JpaytonWPD 2015年

1
你尝试过什么吗?
吉尔斯·奎诺

2
jq . <<< "$json"它与外壳(bash)相关,不特定于jq
Gilles Quenot 2015年

1
缺少括号:arr=( $(...) )
Gilles Quenot 2015年

4
很棒的jq命令,但是请不要将命令输出解析为一个数组arr=( $(...) )(即使它恰好与示例输入配合使用):它不适用于嵌入式或前导/尾随空白,并且可能导致意外的泛滥。
mklement0 '16

5

以下实际上是越野车:

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

而是使用:

# GOOD (with bash 4.x+), but can't detect failure
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

甚至更好

# GOOD (with bash 3.x+), *and* has nonzero status if curl or jq fails
IFS=$'\n' read -r -d '' -a arr \
  < <(set -o pipefail; curl --fail -k "$url" | jq -r '.[].item2' && printf '\0')

2

多亏了sputnick,我才明白了这一点:

arr=( $(curl -k https://localhost/api | jq -r '.[].item2') )

我拥有的JSON是API的输出。我要做的所有工作都是删除file参数,并将|curl的输出通过管道传递到jq。效果很好,并节省了一些步骤。


该代码实际上有点bug。看一下如果您有一个result元素会发生什么*-它会被当前目录中的文件列表替换。
查尔斯·达菲

1
同样,其中item2包含空格的值将成为多个数组元素。
查尔斯·达菲

0

作为一种简单的选择,请查看jtc工具(位于https://github.com/ldn-softdev/jtc),以实现相同的目的(如jq的示例):

bash $ arr=( $(jtc -w '<item2>l+0' file.json) )
bash $ printf '%s\n' "${arr[@]}"
"value2"
"value2_2"
bash $ 

-w选项说明:尖括号<...>指定搜索整个json,后缀l指示搜索标签而不是值,+0指示查找所有出现的内容(而不仅仅是第一个)。


与所有arr=( $(jq ...) )答案相同的错误,只不过是将内容进行字符串拆分和glob扩展以填充数组-意味着空格(而不仅仅是换行符)创建了新元素,而看起来像glob表达式的元素被替换为文件表达式匹配。
查尔斯·达菲,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.