如何使用jq过滤不在列表中的选择项?

dei*_*tch 9 arrays select json blacklist jq

在JQ,我可以选择一个项目很容易的列表:

$ echo '["a","b","c","d","e"]' | jq '.[] | select(. == ("a","c"))'
Run Code Online (Sandbox Code Playgroud)

或者如果您希望将其作为数组:

$ echo '["a","b","c","d","e"]' | jq 'map(select(. == ("a","c")))'
Run Code Online (Sandbox Code Playgroud)

但是,如何选择列表中没有的所有项目?当然. != ("a","c")不起作用:

$ echo '["a","b","c","d","e"]' | jq 'map(select(. != ("a","c")))'
[
  "a",
  "b",
  "b",
  "c",
  "d",
  "d",
  "e",
  "e"
]
Run Code Online (Sandbox Code Playgroud)

上面给出了每个项目两次,除了"a""c"

同样的:

$ echo '["a","b","c","d","e"]' | jq '.[] | select(. != ("a","c"))'
"a"
"b"
"b"
"c"
"d"
"d"
"e"
"e"
Run Code Online (Sandbox Code Playgroud)

如何过滤匹配的项目?

pea*_*eak 8

最简单和最健壮(wrt jq版本)的方法是使用内置-:

$ echo '["a","b","c","d","e"]' | jq -c '. - ["a","c"]'
["b","d","e"]
Run Code Online (Sandbox Code Playgroud)

如果黑名单很长并且有重复,那么删除它们可能是合适的(例如unique).

变化

这个问题也可以用解决(在JQ 1.4及以上)indexnot,如

["a","c"] as $blacklist
| .[] | select( . as $in | $blacklist | index($in) | not) 
Run Code Online (Sandbox Code Playgroud)

或者,从命令行传入变量(jq --argjson blacklist ...):

.[] | select( . as $in | $blacklist | index($in) | not) 
Run Code Online (Sandbox Code Playgroud)

要保留列表结构,可以使用map( select( ...) ).

使用jq 1.5或更高版本,您也可以使用anyall,例如

def except(blacklist):
  map( select( . as $in | blacklist | all(. != $in) ) );
Run Code Online (Sandbox Code Playgroud)

特例:字符串

请参阅例如,基于jq中的多个值选择条目