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

时间:2017-06-15 08:56:56

标签: arrays json select jq blacklist

在jq中,我可以非常轻松地在列表中选择项:

$ echo '["a","b","c","d","e"]' | jq '.[] | select(. == ("a","c"))'

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

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

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

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

上述内容为每个项目提供两次,"a""c&#34除外;

同样的:

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

如何过滤 out 匹配的项目?

2 个答案:

答案 0 :(得分:8)

最简单,最强大(w.r.t.jq版本)的方法是使用内置-

$ echo '["a","b","c","d","e"]' | jq -c '. - ["a","c"]'
["b","d","e"]

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

变体形式

使用indexnot也可以解决问题(在jq 1.4及更高版本中),例如

["a","c"] as $blacklist
| .[] | select( . as $in | $blacklist | index($in) | not) 

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

.[] | select( . as $in | $blacklist | index($in) | not) 

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

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

def except(blacklist):
  map( select( . as $in | blacklist | all(. != $in) ) );

特例:字符串

参见例如Select entries based on multiple values in jq

答案 1 :(得分:2)

I'm sure it is not the most simple solution, but it works :)

$ echo '["a","b","c","d","e"]' | jq '.[] | select(test("[^ac]"))'

Edit: one more solution - this is even worse :)

$ echo '["a","b","c","d","e"]' | jq '.[] | select(. != ("a") and . != ("b"))'