notebook

都内でWEB系エンジニアやってます。

jqで任意の件数だけ出力する

簡単にできるやろと思ったらそんなことなかったのでメモしておく

件数指定する

単純に件数を指定するだけであればlimitでOK

$ echo '[1,2,3,4,5,6,7,8,9,10]' | jq 'limit(3; .[])'
1
2
3

これは簡単

絞り込みや並び替え後に件数指定する

上記のような単純な処理のみであれば問題ないのだが、selectを使いだすと何か処理させた後にパイプで渡ってくる値がどのような状態か意識しないとうまくいかなくなる

  • リストから偶数を3件出力する
$ echo '[1,2,3,4,5,6,7,8,9,10]' | jq 'limit(3; .[]|select(.%2==0))'
2
4
6
  • リストから偶数を降順で3件出力する(パターン1)
$ echo '[1,10,2,9,3,8,4,7,5,6]' | jq 'limit(3; [.[]|select(.%2==0)]|sort|reverse|.[])'
10
8
6
  • リストから偶数を降順で3件出力する(パターン2)
echo '[1,10,2,9,3,8,4,7,5,6]' | jq '[.[]|select(.%2==0)]|sort|reverse|limit(3; .[])'
10
8
6

ポイントは下記のように外側の[]でselectの結果を配列にしている箇所

[.[]|select(.%2==0)]

sortやlimitは配列を期待しているのでselectした結果をそのままパイプで渡すとうまくいかない

  • うまくいかない例
$ echo '[1,10,2,9,3,8,4,7,5,6]' | jq '.[]|select(.%2==0)|sort|reverse|limit(3; .[])'
jq: error (at <stdin>:1): number (10) cannot be sorted, as it is not an array

当たり前といえばそうなのだが、Ruby脳と組み合わさるとこのあたりの感覚が狂ってくる

まとめ

jqで配列を扱う場合はパイプで次の処理に渡すデータの単位を意識しよう