我有一个json文件test.json,其内容为:
[
{
"name": "Akshay",
"id": "234"
},
{
"name": "Amit",
"id": "28"
}
]
我有一个shell脚本,其中包含以下内容:
#!/bin/bash
function display
{
echo "name is $1 and id is $2"
}
cat test.json | jq '.[].name,.[].id' | while read line; do display $line; done
我希望将单个项目的名称和ID作为参数一起传递给函数display,但输出如下所示:
name is "Akshay" and id is
name is "Amit" and id is
name is "234" and id is
name is "28" and id is
正确的代码实现方式应该是什么?PS:我特别想使用jq,所以请根据jq回答
2条答案
按热度按时间pftdvrlh1#
下面是两个主要问题和一些附加项,它们对于当前的示例用例可能无关紧要,但在处理来自不可信来源的真实数据时可能非常重要:
id
之前迭代 * 所有 *name
。while
循环迭代。while
循环时,该循环在子shell中运行;当管道退出时,subshell也退出,因此循环设置的所有变量都将丢失。jq
直接从test.json
读取数据相比,启动/bin/cat
的副本并让jq
从其输出中读取管道是愚蠢和低效的。我们可以解决所有这些问题:
name
s和id
s成对写入,您需要更类似于jq '.[] | (.name, .id)'
的内容while IFS= read -r name && IFS= read -r id; do ...
迭代这些元素对。jq
的-j
参数,然后向正在编写的内容中添加显式的"\u0000"
元素。您需要为每个read
添加-d ''
参数。while read
循环移出subshell,我们可以使用process substitution,如BashFAQ #24中所述。jq
直接从test.json
读取,可以使用<test.json
让shell将文件直接连接到jq的stdin,或者在jq的命令行上传递文件名。以一种对包含JSON编码的NULL的输入数据具有鲁棒性的方式执行上面描述的所有操作将如下所示:
您可以在www.example.com上看到上面运行的代码https://replit.com/@CharlesDuffy2/BelovedForestgreenUnits#main.sh
uklbhaso2#
可以使用字符串插值。
结果:
如果要去掉每个对象的双引号,则:
https://jqplay.org/s/-lkpHROTBk0