jq - 如何 select 基于 'whitelist' 的 属性 值的对象

jq - How to select objects based on a 'whitelist' of property values

因为一个例子胜过一千个字,假设我有以下 JSON 流:

{"a": 0, "b": 1}
{"a": 2, "b": 2}
{"a": 7, "b": null}
{"a": 3, "b": 7}

如何保留 .b 属性 是 [1, 7] 之一的所有对象(实际上列表要长得多所以我不想做 select(.b == 1 or .b == 7)).我正在寻找这样的东西:select(.b in [1, 7]),但我在手册页中找不到我要找的东西。

可以使用模式 select($value == $collection[]) 实现 $value in $collection。一个更有效的替代方法是 select(any($value == $collection[]; .)) 所以你的过滤器应该是这样的:

[1, 7] as $whitelist | select(any(.b == $whitelist[]; .))

将数组放在变量中有其好处,因为它可以让您使用参数轻松更改白名单。

$ jq --argjson whitelist '[2, 7]' 'select(any(.b == $whitelist[]; .))'

以下使用 index/1 的方法类似于最初寻求的方法 (".b in [1, 7]"),并且可能比在 select 中使用 .[] 快得多如果白名单很大。

如果你的jq支持--argjson:

jq --argjson w '[1,7]' '. as $in | select($w | index($in.b))'

否则:

jq --arg w '[1,7]' '. as $in | ($w|fromjson) as $w | select($w | index($in.b))'

或:

jq '. as $in | select([1, 7] | index($in.b))'

更新

2017 年 1 月 30 日,添加了名为 IN 的内置函数,用于高效测试流中是否包含 JSON 实体。它还可以用于有效地测试数组中的成员资格。例如,上面使用 --argjson 的调用可以简化为:

jq --argjson w '[1,7]' 'select( .b | IN($w[]) )'

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

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