我正在和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有点奇怪。以下是一些更直接的解决方案:
select( .author as $a | ["Gary", "Larry"] | index($a) )
Run Code Online (Sandbox Code Playgroud)
["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)
您可以使用对象,就像将它们设置为测试成员资格一样。对数组进行操作的方法效率很低,尤其是在数组可能很大的情况下。
您可以在读取输入之前建立一组值,然后使用该组来过滤输入。
$ 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)