[jqコマンド] サンプル「csvファイルをパースしてJavascriptへ受け渡す」

2019年1月4日

jq テクノロジー プログラミング

jqコマンドをだいぶ使いこなしてきて、自作のフレームワークのデータベースへ組み込みもできる様になってきました。 世の中全てのデータがjsonでやりとりされればいいのですが、まだまだcsvデータも残っているのが現状です。 この間、金融庁でダウンロードしてきた株価データや企業情報、郵便局からダウンロードした郵便番号データなどは、余裕でcsvフォーマットです。 このcsvフォーマットというのは、文字エンコードが"Shift-JIS"という、サーバー業界で"UTF-8"を標準にしようと頑張っている中、トラブルも多いこのエンコード技術を使い続けていて、非常にやっかいです。 そう考えると、Shift-JISデータは、「古い」という感覚は拭えません。 とりあえず、文字エンコードはおいといて、とある会社の株価情報を取得したものをjqコマンドを使ってPHPに取り込んだ時のコマンドサンプルを掲載しておきます。

csvデータとコマンド

20181203,940,958,939,942,54600,942 20181204,852,890,851,868,391700,868 20181205,845,870,840,851,122500,851 20181206,854,855,798,807,146000,807 20181207,806,825,799,803,57700,803 20181210,805,805,770,772,82700,772 20181211,787,787,726,735,137200,735 20181212,740,779,740,775,72000,775 20181213,775,812,765,788,89900,788 20181214,773,781,744,749,75500,749 json形式でもないこのデータをどうやってjqコマンドで受け取るかというと・・・ jq -s -c -R '[ split("\n") | .[] | split(",") | {date: .[0] , start: (.[1] | tonumber?) , max : (.[2] | tonumber?) , min : (.[3] | tonumber?) , end : (.[4] | tonumber?) , volume : (.[5] | tonumber?)} ]' company.csv

解説

最初にsplitが2つ並んでいるのは、「改行コード」と「,カンマ」で縦横の分解をしています。 注意点としては、-sオプションの"--slurp"をつけることを忘れない様にしましょう。 ※このオプションをつけていないと、最後に行毎のデータを配列として繋げなれなくなります。 マルチバイト文字列が入っている場合は、エンコード対応をしなければいけないのですが、今回は株価データということもあり、数値だけだったので、その点は楽できました。 ※後日エンコードタイプもサンプルアップします。 csvは分解さえできてしまえば、あとは、単なる配列処理なので、出力用のjson形式を整えてあげるだけです。 しかしここでもう一つ落とし穴があり、数値データだけとはいえ、csvを分解するときに、全てのデータを文字列化してsplitを行うため、全ての値が"string"になってしまいます。 そして型変換のために、"tonumber"コマンドを使うといいでしょう。 このコマンドは、文字列化された数値を型変換してくれるのですが、数値の桁数が多い場合に入ってしまう","カンマなどがあると、数値化できずにエラーになってしまうので要注意です。 また、csvの場合は、空行なども存在するため、ブランク文字列に対してもエラーになってしまいます。 その場合は、tonumberの後ろに"?"をつけることで、エラー回避してくれるようになるので、禁則処理としてセットしておきましょう。 あっ!そういえば、","カンマが数値に含まれていると、splitで分解されてしまいますね。 そういうデータの含まれたcsvを使う場合は、別の分解方法を行わないといけないのですが、今回は手抜きでそこまで書きません。 今このデータが処理できればいいのです。

結果出力

[ { "date": "20181203", "start": 940, "max": 958, "min": 939, "end": 942, "volume": 54600 }, { "date": "20181204", "start": 852, "max": 890, "min": 851, "end": 868, "volume": 391700 }, { "date": "20181205", "start": 845, "max": 870, "min": 840, "end": 851, "volume": 122500 }, { "date": "20181206", "start": 854, "max": 855, "min": 798, "end": 807, "volume": 146000 }, { "date": "20181207", "start": 806, "max": 825, "min": 799, "end": 803, "volume": 57700 }, { "date": "20181210", "start": 805, "max": 805, "min": 770, "end": 772, "volume": 82700 }, { "date": "20181211", "start": 787, "max": 787, "min": 726, "end": 735, "volume": 137200 }, { "date": "20181212", "start": 740, "max": 779, "min": 740, "end": 775, "volume": 72000 }, { "date": "20181213", "start": 775, "max": 812, "min": 765, "end": 788, "volume": 89900 }, { "date": "20181214", "start": 773, "max": 781, "min": 744, "end": 749, "volume": 75500 } ] うむ、なんのも問題もなくクリアできました。 とはいってもこの処理を作るのに、ハマりまくって半日費やしたんですけどね!

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。