我有以下jq代码片段:
https://jqplay.org/s/QzOttRHoz1
我想使用bash循环结果数组中的每个元素,如伪代码显示:
#!/bin/bash
foreach result
print "My name is {name}, I'm {age} years old"
print "--"
结果将是:
My name is A, I'm 1 years old.
---
My name is B, I'm 2 years old.
---
My name is C, I'm 3 years old.
---
当然,这只是一个简单的例子,只是为了澄清我的目标是分别从jq结果中操纵每个数组。
关于如何将伪代码写入有效的bash语句的任何建议?
保存json:
{
"Names": [
{ "Name": "A", "Age": "1" },
{ "Name": "B", "Age": "2" },
{ "Name": "C", "Age": "3" }
]
}
as /tmp/input.txt我可以运行:
</tmp/input.txt jq --raw-output 'foreach .Names[] as $name ([];[];$name | .Name, .Age )' \
| while read -r name && read -r age; do
printf "My name is %s, I'm %d years old.\n" "$name" "$age";
printf -- "--\n";
done
带有--raw-output
的| .Name, .Age
每个.Names数组成员打印两行,一个带有名字,另一个带有年龄。然后我用while read && read
一次读两行,并用它来循环它们。
如果您愿意:
["A","1"]
["B","2"]
["C","3"]
令人遗憾的是,最好的方法是编写一个完整的解析器,将"\""
等字符串考虑在内。无论如何,你可以:
</tmp/input2.txt sed 's/^\[//;s/\]$//;' \
| while IFS=, read name age; do
name=${name%\"};
name=${name#\"};
age=${age%\"};
age=${age#\"};
printf "My name is %s, I'm %d years old.\n" "$name" "$age";
printf -- "--\n";
done
第一个sed删除了每行中的前导和封闭的[
和]
。然后我读了两个由,
分隔的字符串(所以像"a,b","c,d"
这样的变量将被错误地读取)。然后这两个字符串被剥去了领先和封闭的"
。然后usuall printf用于输出结果。
我有一个简单的脚本来实现你所需要的:
我的Json文件test.json
类似于你的代码片段:
{
"Names": [
{ "Name": "A", "Age": "1" },
{ "Name": "B", "Age": "2" },
{ "Name": "C", "Age": "3" }
]
}
我的剧本:
#!/bin/bash
for i in $(cat test.json | jq -r '.Names[] | @base64'); do
_jq() {
echo ${i} | base64 --decode | jq -r ${1}
}
echo "My Name is $(_jq '.Name'), I'm $(_jq '.Age') years old"
done
请注意,foreach .Names[] as $name ([];[];$name | .Name, .Age )
可以简化为:
.Names[] | ( .Name, .Age )
甚至在这种特殊情况下:
.Names[][]
或者就此而言:
.[][][]
然而,重要的一点是,不需要foreach
来实现简单的迭代。