如何使用bash操纵jq输出?

问题描述 投票:1回答:3

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

bash jq
3个回答
1
投票

保存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用于输出结果。


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

1
投票

请注意,foreach .Names[] as $name ([];[];$name | .Name, .Age )可以简化为:

.Names[] | ( .Name, .Age )

甚至在这种特殊情况下:

.Names[][]

或者就此而言:

.[][][]

然而,重要的一点是,不需要foreach来实现简单的迭代。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.