如何使用bash操纵jq输出?

时间:2018-09-11 21:58:42

标签: bash jq

我有以下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语句的任何建议?

3 个答案:

答案 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不需要实现简单的迭代。