サイトアイコン IT NEWS

【Linux】CSVファイルを指定した行数で均等に分割する方法

linux-split-csv

これまで、CSVファイルの文字コードを変更して、データベースに一括登録する方法をご紹介してきましたが、ここまで来てメモリ不足という物理的な問題にぶつかってしまいました。
CSVファイルのサイズが巨大過ぎて、処理できなかったのです。
そこで今回は、Linuxsplitコマンドを使って、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.

以上、お疲れ様でした。

モバイルバージョンを終了