jqで階層構造になったデータから特定の値を持った、特定の階層のデータを抽出するとき。

select(.name == "value")

特定の値を持ったデータを抽出するにはselect(.name == "value")を使わなければならない。

select(.name == "value")の入力と出力

select()は左から投入した配列の階層構造のまま抽出を行って、右側に出力する。オブジェクトの配列について、そのままselect()すると、ルート(root, ., トップ, top)にある配列ごと返されてしまい、意味がない。
$ cat a.json
[
  {
    "k": 1
  },
  {
    "k": 2
  }
]

$ jq 'select(.[].k == 1)' a.json
[
  {
    "k": 1
  },
  {
    "k": 2
  }
]

階層を降りてからselect()する

階層を掘り下げた、特定の階層の値を得るには、いったん階層を降りてからselect()する。ルート(root, ., トップ, top)からselect()を使わず、事前に特定の階層を指定してからパイプでselect()に渡す。select()の引数に入れておくと得られるデータの階層は下がらないが、select()の左側の外に出すと、階層が下がる。
$ jq '.[] | select(.k == 1)' a.json
{
  "k": 1
}

特定の属性の値で配列を生成する

上で使った、配列に並んだ複数のオブジェクトについて、"k"という属性の値だけを並べた配列は以下のようになる。
$ jq '[ .[].k ]' a.json
[
  1,
  2
]

違う階層の値を1つのオブジェクトに集める

異なるタイプのデータが階層的な配列かオブジェクトで構成されているとき、複数の階層から値を取り出したい場合がある。配列の中にオブジェクトのオブジェクトがあるb.jsonの場合:
$ jq '.' b.json
[
  {
    "d": [
      {
        "e": 1
      }
    ],
    "k": 1
  },
  {
    "d": [
      {
        "e": 10
      }
    ],
    "k": 2
  },
  {
    "d": [
      {
        "e": 100
      }
    ],
    "k": 3
  }
]

b.jsonから、"k"と"e"を対で取り出すとき、"k"については.kで取り出しておき、"v"についてはサブクエリかサブコマンドのように () で囲んで"フィルタ"を書けばよい。この場合は、"v"の値にそのまま"e"の値を積み込みたいので、サブコマンドの最後は.eになっている。サブコマンドの最後をselect()のままにすると "v":[ "e": 10 ] になってしまう。

$ jq '.[] | {"k": .k, "v": ( .d [] | select(.e == 10) | .e ) } ' b.json
{
  "v": 10,
  "k": 2
}

特定の階層のデータから、2次元配列を作る

scikit-learnやscipy, numpy用の2次元配列を作る場合は、出力形式にキー名を書かないため、丸かっことブラケットの羅列になる。出力を簡潔にするため、jqコマンドに-c (compact)オプションを追加した。全体をひとつの配列にするには、"フィルタ"の先頭にブラケット([)をおかなければならない。属性値がない場合は、null が返る。jqには、複数に階層化されたオブジェクトを1階層にするflatten()という関数もあるが、属性名の衝突が起こったときにどうなるかわからない。
$ jq -c '
[			# 2次元配列で返す: 出力・第1階層目
  .[] | [		# 配列全体について: 出力・第2階層目
    .k,			# 配列値1: 入力第1階層の k: の値
    (.d [] | .e )	# 配列地2: 入力第2階層の配列内のオブジェクトのうち e: の値
  ]			
]' b.json

[[1,1],[2,10],[3,100]]

しかしこれは、"filter"ではなくて、「評価式 (eval expression)」だろう。

例はかなり単純にしたが、ちょっと掘り下げて書くと、1行はかなりわかりにくい。宣言型で短く書けるのはよいが、説明文を10行ぐらい書きたくなる。入力形式、出力形式、抽出条件、階層の位置など、説明のための構文がないのが残念。そうやって書くと、普通のプログラムに戻ってしまうのか ... 。

jqのマニュアルには階層化されたデータを効率よく取り出して表示する例と説明が見当たらない。 jq Tips - 指定した値に合致した情報を取得が、解読の参考になった。

jq 1.5から正規表現を使えるmatch()とtest()がある。match()はマッチした文字列の位置や 後方参照(capture)文字列などをオブジェクトとして利用できるが複雑になる。test()は正規表現がマッチしたかどうかだけがわかるシンプルな関数。

正規表現でselect

正規表現でselectするときはselect()内でtest()すればよい。
$ jq '.[] | select(.name | test("インフラ"))' rooms.json
{
  "name":"昔のインフラ",
  "room_id": 123456
}
{
  "name":"今のインフラ",
  "room_id": 45678
}

selectでand条件

selectに複数の条件をandで適用するときは'&&'ではなくandと書けばよい。
$ jq '.[] | select(.name == "昔のインフラ" and .room_id == 123456)' rooms.json
{
  "name":"昔のインフラ",
  "room_id": 123456
}

recure()という再帰命令が関数になっているところは、スマート。

文字列内にクエリ結果を連結するときは "input is \(.)" のように、文字列内で"フィルタ"を\( ... )で囲めばよい。