考虑一个使用 JSON 对象的故意示例,例如此例,我想将许多数组对象中的每一个的相关 、 和 字段提取id
到firstname
shelllastname
变量中以便进一步(非 JSON)处理。
{
"customers": [
{
"id": 1234,
"firstname": "John",
"lastname": "Smith",
"other": "fields",
"are": "present",
"here": "etc."
},
{
"id": 2468,
"firstname": "Janet",
"lastname": "Green",
"other": "values",
"are": "probably",
"here": "maybe"
}
]
}
对于简单的数据我可以使用这个,
jq -r '.customers[] | (.id + " " + .firstname + " " + .lastname)' <data.json |
while IFS=' ' read id firstname lastname
do
# More processing, but omitted for the example
printf '%s -- %s -- %s\n' "$id" "$firstname" "$lastname"
done
输出
1234 -- John -- Smith
2468 -- Janet -- Green
但当然,如果使用双管firstname
值,例如,这将失败Anne Marie
。将分隔符更改为另一个字符,例如,#
感觉更像是敷衍,而不是解决方案,但可以接受。
对于更复杂的情况,我可能会挑选出值列表id
,然后通过回头提取相应的firstname
和lastname
元素来以速度换取准确性。就像这样:
jq -r '.customers[].id' <data.json |
while IFS= read id
do
block=$(jq -r --arg id "$id" '.customers[] | select(.id == $id)' <data.json);
firstname=$(jq -r '.firstname' <<<"$block")
lastname=$(jq -r '.lastname' <<<"$block")
# More processing, but omitted for the example
printf '%s -- %s -- %s\n' "$id" "$firstname" "$lastname"
done
输出
1234 -- John -- Smith
2468 -- Janet -- Green
但是,这两种方法都不是正确且高效的。虽然我不会频繁运行实际代码,但我想知道是否有更合适的方法可以安全有效地将多个数据元素从 JSON 对象结构中取出并放入 shell 变量中?
我并不认为选择其他分隔符(例如制表符)有什么问题。它是 Unix 数据处理应用程序中非常传统的分隔符选择(例如,
paste
and的默认分隔符),并且它不太可能作为名称或 ID 号的一部分出现。and有一个您可以使用的输出运算符:cut
jq
@tsv
我会使用
@tsv
过滤器:对于空字段要小心,因为它们
read
可能会“中断”;您应确保每个字段始终输出至少一个字符。注意:用于
%b
解码转义@tsv
序列