26

我有一个像这样行的文件:

{"items":["blue","green"]}
{"items":["yellow","green"]}
{"items":["blue","pink"]}

如何使用jq选择并仅显示在其“项目”数组中具有“蓝色”的 JSON 值?

所以输出将是:

{"items":["blue","green"]}
{"items":["blue","pink"]}
4

4 回答 4

21

找到了答案

jq 'select(.items | index("blue"))'
于 2014-09-03T17:37:41.187 回答
9

2017 年 1 月 30 日,IN添加了一个名为的内置函数,用于有效测试 JSON 实体是否包含在流中。它还可以用于有效地测试数组中的成员资格。在本案中,相关用法为:

select( .items as $items | "blue" | IN($items[]) )

如果你的 jq 没有IN/1,那么只要你的 jq 有first/1,你就可以使用这个等价的定义:

def IN(s): . as $in | first(if (s == $in) then true else empty end) // false;

任何/0

在这里使用any/0效率相对较低,例如与使用相比any/1

select( any( .items[]; . == "blue" ))

(实际上,index/1通常速度足够快,但目前(jq 1.5 和至少到 2017 年 7 月的版本)的实现并不理想。)

于 2017-07-02T03:25:01.203 回答
5

虽然你所拥有的肯定有效,但使用contains. 我会避免这种使用,因为它会导致混乱。 index("blue")0并且人们不会认为这是一个真实的值,并且可能会期望它被排除在结果之外。

考虑改用这个过滤器:

select(.items | contains(["blue"]))

这有一个额外的好处,如果您想要通过简单地向数组添加更多匹配项来匹配多个匹配项,它会起作用。

正如威尔在评论中指出的那样,这并不完全正确。字符串在此处使用子字符串匹配(contains递归使用)进行比较。

回想起来,contains并没有像我想象的那样成功。使用index作品,但我个人不会使用它。通过查找对我来说感觉不对的索引来确定一个项目是否在集合中。使用contains对我来说更有意义,但鉴于这些信息,在这种情况下它并不理想。


这是一个应该正常工作的替代方案:

select([.items[] == "blue"] | any)

或者,如果您希望能够匹配更多值,则可以采用更具可扩展性的方式:

select(.items as $values | ["blue", "yellow"] | map([$values[] == .] | any) | all)
于 2014-09-04T01:54:30.983 回答
2

对于对象的相同情况,我需要使用“正则表达式”。(当然,在另一种情况下)。我编写代码是因为我没有在这些页面中找到满足我需求的解决方案。这可能对某人有用。

例如,要使用正则表达式匹配蓝色:

jq 'select(.items[]|test("bl.*"))' yourfile.json

jq播放

于 2018-12-19T10:41:27.117 回答