コマンドラインJSONプロセッサー jqのオプションとフィルタ


jq(Command-line ISON processer)

jqはJSONデータをスライスしたりフィルタしたりできるプログラムです。
コンソール上でJSONデータをきれいにインデント、ハイライトして表示することもできるのでJSONビューワーとしても使えます。
jqはc言語で書かれており、特定のライブラリに依存しません。
Windows,MacOS,Linuxなど多くのプラットフォームに対応しています。

jqの使い方

jsonコマンドの書式

jq [options...] filter [files...]

オプション

--version
バージョンをアウトプットして、exitステータス0で終了する
--slurp/-s
各JSONオブジェクトに対してフィルタを実行する代わりに、全てのインプットストリームを読み込み配列に入れて1度だけフィルタを実行する
--online-input/-I
トップレベルのインプットの値が1つの配列のとき、配列の代わりにそのエレメントを提供する。非常に大きくなるかもしれないトップレベルの配列の要素をオンラインで処理することを許可する。
--raw-input/-R
JSONとしてパースしない。代わりに各業のテキストを文字列としてフィルタに渡す。--slurpと組み合わせるとインプットの全てが1つの文字列としてフィルタに渡される。
--null-input/-n
インプットを全く読み込まない。代わりにインプットをnullとしてフィルタを1度だけ実行する。
これはjqをシンプルな計算機として使うときや、JSONデータをゼロから構築するときに役立ちます。
--compact-output / -c
デフォルトではjqはJSONアウトプットをインデントや改行をしてきれいに表示します。このオプションを使うと、結果は1行で表示されて、よりコンパクトなアウトプットになります。
--colour-output / -C and --monochrome-output / -M
jqはターミナルにアウトプットする時にはデフォルトで色付けしてアウトプットします。-Cを使うとpipeやファイルに出良くする時にも色付けを強制できます。色付けを無効にするには-Mを使います。
--ascii-output / -a
インプットが”\u03bc”のようなエスケープシーケンスを指定していたとしても、jqは通常ASCIIではないUTF-8としてのユニコード符号位置をアウトプットします。
すべてのASCIIではない文字をエスケープシーケンスと同様に置き換えて、純粋なASCIIアウトプットを強制することができます。
--unbuffered

各JSONオブジェクトが表示された後にアウトプットを消去する。(jqに遅いデータをパイプしているときやjqのアウトプットをどこかにパイプしている場合に便利)
--sort-keys / -S
並び順を揃えたキーと共に各オブジェクトのフィールドをアウトプットする。
--raw-output / -r
このオプションはフィルタの結果が文字列ならば、JSON書式のクオーテーション付き文字列ではなく、文字列を標準出力に直接アウトプットする。jqフィルタをJSONベースではないシステムと連携させるときに役立つ。
-f filename / --from-file filename
awkの-fオプションのようにフィルターをコマンドラインからではなくファイルから読み込む。”#”を使ってコメントを書くこともできる。
-e / --exit-status
最後のアウトプットがfalseでもnullでもないときにjqのexitステータスを0にする。
0: jqプログラム実行
1: 最後のアウトプットがfalseか0
2: なんらかのコマンド書式の問題
3: jqプログラムのコンパイルエラー
4: 正しい結果を生成できない
--arg name value
このオプションは値をjqプログラムに定義済みの変数として渡します。jqを--arg foo barのオプションとともに実行すれば$fooは値”bar”を持つ変数としてプログラム内で使用できます。
--argfile name filename
このオプションは指定されたファイルから最初の値を定義済み変数としてjaプログラムに渡します。jqを--argfile foo barのオプションとともに実行すれば$fooはbarという名前のファイルの内容を値にもつ変数としてプログラム内で使用できます。

フィルタ

.
最もシンプルなフィルタは.(ドット)です。インプットを何も変更せずにアウトプットします。

jq '.'
   "Hello, world!"
=> "Hello, world!"
.foo, .foo.bar
シンプルで役立つフィルタは.fooフィルタです。JSONオブジェクトがインプットとして与えられたときに”foo”キーの値を返します。もし指定のキーが見つからなければnullを返します。

      jq '.foo'
   {"foo": 42, "bar": "less interesting data"}
=> 42

jq '.foo'
   {"notfoo": true, "alsonotfoo": false}
=> null

jq '.["foo"]'
   {"foo": 42}
=> 42
.foo?
fooに似ていますが、. が配列やオブジェクトでないときもエラーを返しません。

jq '.foo?'
   {"foo": 42, "bar": "less interesting data"}
=> 42

jq '.foo?'
   {"notfoo": true, "alsonotfoo": false}
=> null

jq '.["foo"]?'
   {"foo": 42}
=> 42

jq '[.foo?]'
   [1,2]
=> []
.[], .[2], .[10:15]
オブジェクトのフィールドを.[“foo”]のように検索することができます。(上記の.fooはこれを短く書いたものです。)
キーが整数の場合、これは配列に適用できます。配列のインデックスは0から始まりますので.[2]は配列の3つ目の要素を返します。
.[10:15]の構文は1つの配列からスライスした配列や文字列のスライスを返します。.[10:15]を配列に適用するとインデックス10から15までの値を持つ長さ5の配列を返します。どちらのインデックスもマイナスの値を持てます(配列の後ろから数える数になります)。また先頭と配列の最後を指定する場合はインデックスの省略もできます。
?オペレータは.[10:15]?のようにスライスオペレータとともに使えます。これはスライス可能な位置の値を返します。

jq '.[0]'
   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> {"name":"JSON", "good":true}

jq '.[2]'
   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> null

jq '.[2:4]'
   ["a","b","c","d","e"]
=> ["c", "d"]

jq '.[2:4]'
   "abcdefghi"
=> "cd"

jq '.[:3]'
   ["a","b","c","d","e"]
=> ["a", "b", "c"]

jq '.[-2:]'
   ["a","b","c","d","e"]
=> ["d", "e"]
.[]
.[index]を使うときにindexを完全に省略すると配列のすべての要素を返します。
.[]をインプット[1,2,3]に実行すると1つの配列ではなく個々の数字が返ります。
これはオブジェクトに対しても使えます。そしてそれはすべてのオブジェクトの値を返します。

jq '.[]'
   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> {"name":"JSON", "good":true}, {"name":"XML", "good":false}

jq '.[]'
   []
=>

jq '.[]'
   {"a": 1, "b": 1}
=> 1, 1
.[]?
.[]と同じようにフィルタしますが、. が配列やオブジェクトでない場合もエラーを返しません。
,
2つのフィルタを,(コンマ)で区切るとインプットには両方が適応され、複数のアウトプットを得ます。
まず、すべてのアウトプットは左の句から右の句の順番で生成されます。
例えば、フィルタ ‘.foo , .bar’ はfooフィールドとbarフィールドを別々にアウトプットします。

jq '.foo, .bar'
   {"foo": 42, "bar": "something else", "baz": true}
=> 42, "something else"

jq '.user, .projects[]'
   {"user":"stedolan", "projects": ["jq", "wikiflow"]}
=> "stedolan", "jq", "wikiflow"

jq '.[4,2]'
   ["a","b","c","d","e"]
=> "e", "c"
|
|(パイプ)オペレータは2つのフィルタを結合します。右の1つのフィルタのアウトプットに対して次のフィルタを適応します。Unixシェルのパイプと大変よく似ています。
左のフィルタが複数の結果を生成するとき、右のフィルタはそれぞれの結果に対して実行されます。
ですから ‘.[] | .foo’ という句はインプット配列の各要素の.fooフィールドを取得します。

jq '.[] | .name'
   [{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> "JSON", "XML"