我有多个json文件:
a.json
{
"status": "passed",
"id": "id1"
}
{
"status": "passed",
"id": "id2"
}
b.json
{
"status": "passed",
"id": "id1"
}
{
"status": "failed",
"id": "id2"
}
我想知道a.json
中传递了哪个ID,而b.json
中哪个ID失败了。
expected.json
{
"status": "failed",
"id": "id2"
}
我尝试过类似的事情:
jq --slurpfile a a.json --slurpfile b b.json -n '$a[] | reduce select(.status == "passed") as $passed (.; $b | select($a.id == .id and .status == "failed"))'
$passed
应该包含a.json
中传递的条目列表,而reduce
将合并id匹配且failed
的所有对象。
但是它没有产生预期的结果,文档也有限。
如何从expected.json
和a.json
生成b.json
?
答案 0 :(得分:2)
对我来说,你的过滤器会产生错误
jq: error (at <unknown>): Cannot index array with string "id"
我怀疑这是因为你写了$b
而不是$b[]
和$a.id
而不是$passed.id
。以下是我对你打算写的内容的猜测:
$a[]
| reduce select(.status == "passed") as $passed (.;
$b[] | select( $passed.id == .id and .status == "failed")
)
产生输出
null
{
"status": "failed",
"id": "id2"
}
您可以通过添加null
例如
| values
$a[]
| reduce select(.status == "passed") as $passed (.;
$b[] | select( $passed.id == .id and .status == "failed")
)
| values
但是这里你真的不需要reduce
。一种更简单的方法就是:
$a[]
| select(.status == "passed") as $passed
| $b[]
| select( $passed.id == .id and .status == "failed")
如果你想进一步研究这个问题,我建议采用另一种方法:首先构建一个组合$a
和$b
的对象,然后根据需要设计你想要的对象。 e.g。
reduce (($a[]|{(.id):{a:.status}}),($b[]|{(.id):{b:.status}})) as $v ({};.*$v)
会给你
{
"id1": {
"a": "passed",
"b": "passed"
},
"id2": {
"a": "passed",
"b": "failed"
}
}
要将其转换回您请求的输出,请添加
| keys[] as $id
| .[$id]
| select(.a == "passed" and .b == "failed")
| {$id, status:.b}
获取
{
"id": "id2",
"status": "failed"
}
答案 1 :(得分:1)
以下问题的解决方案主要针对效率,但事实证明它们非常简单明了。
为了提高效率,我们将构建一个&#34;字典&#34;那些已经通过a.json来快速完成所需查找的人的ID。
另外,如果您的jq版本为inputs
,则很容易避免&#34;啜饮&#34; b.json的内容。
这是一个通用的解决方案,然而,它会淹没这两个文件:
调用(注意使用-s选项):
jq -s --slurpfile a a.json -f passed-and-failed.jq b.json
程序:
([$a[] | select(.status=="passed") | {(.id): true}] | add) as $passed
| .[] | select(.status == "failed" and $passed[.id])
即,首先构造字典,然后在b.json中发出满足条件的对象。
调用(注意使用-n选项):
jq -n --slurpfile a a.json -f passed-and-failed.jq b.json
INDEX/2
目前可从master
分支获得,但此处提供以防您的jq没有它,在这种情况下,您可能希望将其定义添加到~/.jq
:
def INDEX(stream; idx_expr):
reduce stream as $row ({};
.[$row|idx_expr|
if type != "string" then tojson
else .
end] |= $row);
解决方案现在变成了一个简单的双线程:
INDEX($a[] | select(.status == "passed") | .id; .) as $passed
| inputs | select(.status == "failed" and $passed[.id])