テキストデータをjsonで統一すると、jqコマンドが便利すぎて極めたくなってきました。
jqコマンドって何かと言うと、jsonデータが記述されたテキストファイルをターミナルコマンドでparseしてデータ検索して取得したり、整形したりできる非常に便利で強力なデータアクセスコマンドです。
以前にブログでも書いたので、jqコマンドについては、以下を参照してください。
JSONファイルをコマンドで扱える「jq」を学習してみる #1「初期設定」
そして今回は、なるべくawkやパイプ繋ぎのshellを使わない様にjqの一発コマンドで行える様にする為に、対応したjqコマンドのサンプルを備忘録として書き溜めておきます。
基本jsonデータ構造
テキストファイルの行毎にjsonフォーマットを格納しているログ形式のjsonデータファイルです。
サンプルは以下のような感じ。
{"column-1" : 1 , "column-2" : 2 , "column-3" : 3}
{"column-1" : 4 , "column-2" : 5 , "column-3" : 6}
{"column-1" : 7 , "column-2" : 8 , "column-3" : 9}
{"column-1" : 10 , "column-2" : 11 , "column-3" : 12}
{"column-1" : 13 , "column-2" : 14 , "column-3" : 15}
各行毎に、同じkey(カラム)名になっていますが、データ統制としては、同じである事が望ましいですが、jqコマンドを使う場合には、必ず同じになっていないといけないわけではありません。
存在するkey値を元に集計できるのは、非常に便利ですね。
元データ
ログデータや、日付を元にしたデータ登録でもっともスタンダードなやり方なので、これをベースにコマンドを書き換えていくとやりやすいと思います。
{"date":20180904,"code":"3909","memo":"test-2"}
{"date":20181205,"code":"3909","memo":"test"}
{"date":20180801,"code":"3909","memo":"aaa-aaa"}
{"date":20180802,"code":"3909","memo":"bbb-bbb"}
{"date":20180808,"code":"3909","memo":"ccc-ccc"}
{"date":20180809,"code":"3909","memo":"eee-eee"}
{"date":20180806,"code":"3909","memo":"fff-fff"}
{"date":20180807,"code":"3909","memo":"ggg-ggg"}
{"date":20180805,"code":"3909","memo":"ddd-ddd"}
{"date":20181202,"code":"3909","memo":"aaa"}
{"date":20181020,"code":"3909","memo":"bbb"}
{"date":20181001,"code":"3908","memo":"test"}
{"date":20181001,"flg":1,"code":"3908"}
{"flg":1,"date":20180802,"code":"3909","memo":"bbb-bbb"}
コマンド
jq -s '[sort_by(.date) | reverse | unique_by(.date) | reverse[] | select(.flg!=1) | {type:"memo" , date:.date , memo:.memo} ]' data_1.json
解説
出力にtypeをつけているのは、このデータを利用するシステム用に設置しています。
出力の際にこのように任意フラグを設置することも可能なので、かなり重宝できまね。
ここでは、jqコマンドの基本的な記述ではなく、コマンド内の核部分を解説します。
[sort_by(.date) | reverse | unique_by(.date) | reverse[] | select(.flg!=1) | {type:"memo" , date:.date , memo:.memo} ]
この部分ですね。
まず、最初に.dateで"sort"して、それを"reverse"しているのは、そのあとのunique_byで、先頭を残して削られてしまうので、追記型のデータでは、下に書かれているものが有効になります。
そのための"reverse"です。
そして、"unique_by"で.dateとして日付を最新情報を残して絞り込みます。
この際になぜかデータが"sort"処理されてしまうので、最新順での出力にする為に、すぐ後で再度"reverse"処理をしています。
ちなみに、このreverseに"[]"をつけているのは、その後のselectなどの操作は、配列内で行う処理になるので、データの切り替え処理だと思ってください。
最新順でなく、古い順の表示をする場合は、この"reverse[]"を無くして、代わりにデータ切り替えとして、"unique_by(.date)"を"unique_by(.date)[]"として切り替えてください。
その後"select"で.flgが1でないものをピックアップ(1を除外)することで論理削除フラグを排除しています。
次に、出力するjsonデータフォーマットを任意に整形しています。{key:value}で、それぞれ値をはめ込む事ができるので、都合のいい形式での出力ができます。
ちなみに、key値に元jsonのvalueを当て込むこともできるので、この辺はデータ設計をきちんと行なった上で実行してください。
そして、最後に一番重要なのが、これらのjsonデータを出力する時に、ログデータの形式のような形では、レコード単位での複数json形式になってしまうので、一括したjson形式にするために、全ての操作を"[**]"で囲ってあげます。
こうすることで、内容した複数のデータを配列にして出力する事が可能になります。
途中で行なったデータ切り替えの逆の操作になります。
結果
[
{
"type": "memo",
"date": 20181205,
"memo": "test"
},
{
"type": "memo",
"date": 20181202,
"memo": "aaa"
},
{
"type": "memo",
"date": 20181020,
"memo": "bbb"
},
{
"type": "memo",
"date": 20180904,
"memo": "test-2"
},
{
"type": "memo",
"date": 20180809,
"memo": "eee-eee"
},
{
"type": "memo",
"date": 20180808,
"memo": "ccc-ccc"
},
{
"type": "memo",
"date": 20180807,
"memo": "ggg-ggg"
},
{
"type": "memo",
"date": 20180806,
"memo": "fff-fff"
},
{
"type": "memo",
"date": 20180805,
"memo": "ddd-ddd"
},
{
"type": "memo",
"date": 20180801,
"memo": "aaa-aaa"
}
]
スピードもかなり早く、簡易なシステムで使うことでわざわざSQLを介す必要もなく、データコントロールができるようになるので、非常に便利です。
0 件のコメント:
コメントを投稿