たとえば
{"users":[{"id":1,"name":"taro"},{"id":2,"name":"hanako"}]}
のようなJSONがあったとして、
1 taro 2 hanako
のように整形して表示させたかった
結論(2020年8月30日追記)
jq単体でできた。コメントしてくださった方ありがとうございます
cat test.json| jq '.users[] | (.id|tostring) + " " + .name' -r
jqコマンド内でパイプのように繋げる方法があった。idでtostringしているのはJSONの数値型だとjqが認識してしまうため。実際つけないと
jq: error (at <stdin>:1): number (1) and string (" ") cannot be added
とエラーになる。
以下過去の戯れ言
結論
jq単体ではできないので xargsコマンドを使う
ruby a.rb | jq -r '.users[] | .id, .name' | xargs -n2
以下ここに至るまでの経緯
経緯
まずはそのまま出力してみる
ruby a.rb | jq '.' { "users": [ { "id": 1, "name": "taro" }, { "id": 2, "name": "hanako" } ] }
なるほど、次はusersだけに絞ってみる。これも問題なさそう
ruby a.rb | jq '.users' [ { "id": 1, "name": "taro" }, { "id": 2, "name": "hanako" } ]
次にidのフィールドのみ表示してみる。usersは配列なので attribute[]
で1つずつ処理されていく
ruby a.rb | jq '.users[].id' 1 2
idだけじゃなくてnameも欲しいとなった場合、「,」で区切ることで複数出力できるらしい。やってみる。「|」でパイプとして区切ってid,nameをそれぞれ出力 あと-r
オプションは文字列をダブルコーテーションで囲まなくする。
ruby a.rb | jq -r '.users[] | .id, .name' 1 taro 2 hanako
は???????なんで複数行に別れてるの??
どうも []
で囲むと配列になるらしい。やってみる
ruby a.rb | jq '.users[] | [.id, .name]' [ 1, "taro" ] [ 2, "hanako" ]
いや、そうではない。。。
パイプの最後に @csv
を指定するとCSV出力になるらしい。確かに冒頭で書いた求めている結果はCSVっぽい形式であり、このオプションを使えばいい感じになるかも!
ruby a.rb | jq -r '.users[] | [.id, .name] | @csv' 1,"taro" 2,"hanako"
あっ、CSVですもんね、、ダブルコーテーションで囲まれますよね。。
で、色々見てたらどうもxargsコマンドで制御できるとのこと
ruby a.rb | jq -r '.users[] | .id, .name' | xargs -n2 1 taro 2 hanako
やったぜ
どういうこと?
xargsのmanには以下のように書いてある
-n max-args, --max-args=max-args 1 コマンドラインにつき最大 max-args 個の引き数を使用する。
つまり、本来だとxargsは1引数しか受けないが、-nをつけることでその数分の引数を同時に受け付けてくれるわけ
わかり易い例が以下
echo 1 2 3 4 5 | xargs -n2 1 2 3 4 5
が、manにも載っている通り、-I
の置き換えオプションが使えなくなってしまうため、更に加工したい場合はxargsとawkを組み合わせるしかない
ruby a.rb | jq -r '.users[] | .id, .name' | xargs -n2 | awk '{print "ID:"$1,"名前:"$2}' ID:1 名前:taro ID:2 名前:hanako
別解
やけくその @tsv
ruby a.rb | jq -r '.users[] | [.id, .name] | @tsv' 1 taro 2 hanako