これまで、CSVファイルの文字コードを変更して、データベースに一括登録する方法をご紹介してきましたが、ここまで来てメモリ不足という物理的な問題にぶつかってしまいました。
CSVファイルのサイズが巨大過ぎて、処理できなかったのです。
そこで今回は、Linuxのsplitコマンドを使って、CSVファイルを行数が均等になるように分割し、指定したファイル数で出力する方法をご紹介します。【参照】これまでの流れ
CSVを同じ行数で分割
それでは、splitコマンドの基本から、使用するオプション、特定のファイル数で分割するための行数の計算方法など、順を追って紹介していきます。
splitコマンドの使い方
基本的にはこれだけで分割できます。
split [オプション] [元ファイル名] [出力ファイル名]
オプションには、-bのバイト数や-lの行単位を指定して分割する方法があります。
基本使用例
# 1000バイト(1kb)で分割する
split -b 1000 data.csv data_# 1000行で分割する
split -l 1000 data.csv data_
しかし、このように分割するとファイル名が、
data_aa
data_ab
data_ac
・・・
という具合に、連番ではなくアルファベットで出力されてしまいます。
これでは、スクリプトでループしたい場合などにとても不便です。
ファイル名を連番にする
それを解決してくれるのが、-dオプションです。
-dオプションを付けると、デフォルトで2桁の数字に変更してくれます。
桁数を変えたい場合は、-aオプションを使います。
# 1000行で分割して、ファイル名に3桁の連番を付ける
split -l 1000 -d -a 3 data.csv data_
実行するとこのようになります。
data_000
data_001
data_002
・・・
ファイル名に拡張子をつける
さぁ!ここで最後の問題!
CSVファイルなのに分割後は拡張子(.csv)が付いてないですよね?
それを解決すべく、更に–additional-suffixオプションを追加します。
その名の通り、これで拡張子を付けてくれるんですね。
splitまとめ
以上のことを踏まえてまとめると、以下のようなコマンドが完成します。
split -l 1000 -d -a 3 data.csv data_ --additional-suffix=.csv
行数を均等に分割する方法
wcコマンドで全体の行数を出し、awkコマンドで割り算した結果を変数に入れます。
rows=`wc -l data.csv | awk '{printf("%d",(($1 / 10) + 1))}'`
ちょっとだけポイントを解説。
ファイルを10分割(/ 10)しています。
“%d”で整数だけを取得。
+ 1は割り切れなかった場合に備えて1を足しています。
1行多くなったりするので、キッチリ均等になりませんが別にいいでしょ?
まとめのまとめ
そして、計算結果を先程の[1000]の箇所に入れてあげれば完成です。
rows=`wc -l data.csv | awk '{printf("%d",(($1 / 10) + 1))}'`
split -l $rows -d -a 3 data.csv data_ --additional-suffix=.csv
番外編
この書き方だけが全てではないのがコンピュータですね。
他の方法も紹介されてましたので、紹介して終わりにします。
以下、ファイルを真っ二つに分割する例です。
split -l $(expr $(wc -l foo.txt | cut -d " " -f 1) / 2 + 1) foo.txt bar.
以上、お疲れ様でした。
- Original:https://minory.org/linux-split-csv.html
- Source:Minory
- Author:管理者
Amazonベストセラー
Now loading...