この入力を考えると:
[
{
"Id": "cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b",
"Names": [
"condescending_jones",
"loving_hoover"
]
},
{
"Id": "186db739b7509eb0114a09e14bcd16bf637019860d23c4fc20e98cbe068b55aa",
"Names": [
"foo_data"
]
},
{
"Id": "a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19",
"Names": [
"jovial_wozniak"
]
},
{
"Id": "76b71c496556912012c20dc3cbd37a54a1f05bffad3d5e92466900a003fbb623",
"Names": [
"bar_data"
]
}
]
私は jq を使ってId
sを持つすべてのオブジェクトを返す含まない内側のNames
配列内の "data"。出力は改行で区切られています。上記のデータについて、私が欲しい出力は
cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19
私はこれにやや近いと思います。
(. - select(.Names[] contains("data"))) | .[] .Id
しかし、select
フィルタは正しくなく、コンパイルもされません(error: syntax error, unexpected IDENT
を取得)。
とても近い! select
式では、contains
の前にパイプ(|
)を使用する必要があります。
このフィルタは予想される出力を生成します。
. - map(select(.Names[] | contains ("data"))) | .[] .Id
jq Cookbook に構文の例があります。
キーの内容に基づいてオブジェクトをフィルタリングする
たとえば、ジャンルキーに「house」が含まれているオブジェクトだけが必要です。
$ json='[{"genre":"deep house"}, {"genre": "progressive house"}, {"genre": "dubstep"}]' $ echo "$json" | jq -c '.[] | select(.genre | contains("house"))' {"genre":"deep house"} {"genre":"progressive house"}
Colin D は、JSONオブジェクトのストリームではなく単一のJSON配列になるように、配列のJSON構造を保持する方法を問い合わせます。
最も簡単な方法は、式全体を配列コンストラクタでラップすることです。
$ echo "$json" | jq -c '[ .[] | select( .genre | contains("house")) ]'
[{"genre":"deep house"},{"genre":"progressive house"}]
Map関数を使うこともできます。
$ echo "$json" | jq -c 'map(select(.genre | contains("house")))'
[{"genre":"deep house"},{"genre":"progressive house"}]
mapは入力配列を解凍し、すべての要素にフィルタを適用して新しい配列を作成します。つまり、map(f)
は[.[]|f]
と同等です。
これは any/2 を使う別の解決策です。
map(select(any(.Names[]; contains("data"))|not)|.Id)[]
サンプルデータとそれが生成する-r
オプションを使って
cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19