web-dev-qa-db-ja.com

jqを使用してリストにない選択項目をフィルタリングする方法

Jqでは、アイテムを選択することができますinリストはかなり簡単です:

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

または、配列として取得したい場合:

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

しかし、リストでnotであるすべてのアイテムを選択するにはどうすればよいですか?確かに. != ("a","c")は機能しません:

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

上記は、_"a"_および_"c_を除くすべての項目を2回提供します。 "

同じ:

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

out一致するアイテムをどのようにフィルタリングしますか?

11
deitch

最も単純で最も堅牢な(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以降では、anyまたはallを使用することもできます。

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

特殊なケース:文字列

たとえば、 jqの複数の値に基づいてエントリを選択

8
peak

私はそれが最も単純な解決策ではないと確信していますが、それはうまくいきます:)

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

編集:もう1つの解決策-これはさらに悪い:)

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