根据jq中的多个值选择条目

DGa*_*aff 3 json whitelist jq

我正在和JQ合作,到目前为止我非常喜欢它.我遇到了一个问题,我还没有找到其他地方的解决方案,并希望看看社区是否有办法做到这一点.

我们假设我们有一个看起来像这样的JSON文件:

{"author": "Gary", "text": "Blah"}
{"author": "Larry", "text": "More Blah"}
{"author": "Jerry", "text": "Yet more Blah"}
{"author": "Barry", "text": "Even more Blah"}
{"author": "Teri", "text": "Text on text on text"}
{"author": "Bob", "text": "Another thing to say"}
Run Code Online (Sandbox Code Playgroud)

现在,我们想要选择值author等于"Gary"或"Larry"的行,但没有其他情况.实际上,我有几千个我正在检查的名字,所以简单地陈述直接或条件(例如cat blah.json | jq -r 'select(.author == "Gary" or .author == "Larry")')是不够的.我试图通过inside像这样的函数来做到这一点,但得到一个错误对话框:

author

cat blah.json | jq -r 'select(.author == "Gary" or .author == "Larry")'

做这样的事情最好的方法是什么?

pea*_*eak 14

inside而且contains有点奇怪。以下是一些更直接的解决方案:

指数/1

select( .author as $a | ["Gary", "Larry"] | index($a) )
Run Code Online (Sandbox Code Playgroud)

任何/2

["Gary", "Larry"] as $whitelist
| select( .author as $a | any( $whitelist[]; . == $a) )
Run Code Online (Sandbox Code Playgroud)

使用字典

如果性能是一个问题,并且“作者”始终是一个字符串,那么应该考虑采用@JeffMercado 建议的解决方案。这是一个变体(与 -n 命令行选项一起使用):

["Gary", "Larry"] as $whitelist
| ($whitelist | map( {(.): true} ) | add) as $dictionary
| inputs
| select($dictionary[.author])
Run Code Online (Sandbox Code Playgroud)


DGa*_*aff 5

IRC用户gnomon在jq频道上回答如下:

jq 'select([.author] | inside(["Larry", "Garry", "Jerry"]))'

这种做法背后的直觉,因为用户说的是:"从字面上看你的想法,只有包装.author[.author]将其强制成是一个单项阵列,inside()将进行这项工作." 此答案为列表中提供的一系列名称生成所需的过滤结果,作为所需的原始问题.

  • 这将执行子字符串搜索。`"Lar"` 和 `"erry"` 和 `"J"` 将全部匹配。 (4认同)

Jef*_*ado 5

您可以使用对象,就像将它们设置为测试成员资格一样。对数组进行操作的方法效率很低,尤其是在数组可能很大的情况下。

您可以在读取输入之前建立一组值,然后使用该组来过滤输入。

$ jq -n --argjson names '["Larry","Garry","Jerry"]' '
(reduce $names[] as $name ({}; .[$name] = true)) as $set
    | inputs | select($set[.author])
' blah.json
Run Code Online (Sandbox Code Playgroud)