我有以下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语句的任何建议?
答案 0 :(得分:1)
保存json:
{
"Names": [
{ "Name": "A", "Age": "1" },
{ "Name": "B", "Age": "2" },
{ "Name": "C", "Age": "3" }
]
}
/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
的{{1}}仅对每个.Names数组成员打印两行,一个带有name,另一个带有age。然后,我用| .Name, .Age
一次读了两行,并用它遍历它们。
如果您愿意:
while read && read
可悲的是,最好的办法是编写一个完整的解析器,该解析器将考虑诸如["A","1"]
["B","2"]
["C","3"]
之类的字符串。无论如何,您可以:
"\""
第一个sed删除了每行中的前导和封闭</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
和[
。然后,我读取了两个由]
分隔的字符串(因此,将错误地读取,
之类的var)。然后,将除去这两个字符串的开头和结尾的"a,b","c,d"
。然后使用通常的printf输出结果。
答案 1 :(得分:1)
我写了一个简单的脚本来实现您所需要的:
我的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
答案 2 :(得分:1)
请注意,foreach .Names[] as $name ([];[];$name | .Name, .Age )
可以简化为:
.Names[] | ( .Name, .Age )
,甚至在这种情况下也可以:
.Names[][]
或者为此:
.[][][]
但是,重要的一点是,foreach
不需要实现简单的迭代。