広告 プログラミング

【解説】シェルスクリプトでテキストをN行ずつに分割(splitコマンドの活用)

※本ページには、プロモーション(広告)が含まれています。

悩んでいる人

シェルスクリプトでテキストをN行ずつに分割したいが、効率的な方法が思いつかない。

効率的な方法を教えて欲しい。

こんなお悩みを解決します。

今回は、シェルスクリプトによる自動化において、任意の行ずつに分割する方法を解説します。

前提条件を取り上げて解説をするので、シェルスクリプトを用いて開発する際の参考になれば幸いです。

前提条件

例えば、以下のように実行したいコマンドをテキストに書き出した状況を想定します。

/opt/commands/job pattern1
/opt/commands/job pattern2
/opt/commands/job pattern3
/opt/commands/job pattern4
/opt/commands/job pattern5

今回は、splitコマンドを用いて、これらを行ずつに分割する方法を解説します。

また、説明の都合上、以下の2点を前提とします。

  • 上記のリストをlists.txtに保存している
  • splitコマンドのバージョンは「8.32」とする。

実行例

上記のlists.txtを2行ずつに分割した場合の例を示します。

この場合、3つに分割されることになり、それぞれの内容は以下のようになります。

# 1つ目のファイルの内容
/opt/commands/job pattern1
/opt/commands/job pattern2

# 2つ目のファイルの内容
/opt/commands/job pattern3
/opt/commands/job pattern4

# 3つ目のファイルの内容
/opt/commands/job pattern5

実装例

今回のケースでは、splitコマンドを利用します。※splitコマンドのオプション(一部)はコチラを参照のこと。

ここでは、以下のオプションを利用してファイル分割を行います。

オプション名用途
-a700行を超えるファイルを分割できるようにするため
-l分割する行数を指定するため
--verbosesplitコマンドの実行により得られたファイルをリネームするため
使用するオプション

実装例は以下のようになります。

#!/bin/bash

count=0
prefix=out
split -a 5 -l 2 --verbose lists.txt | while read dummy target others; do
    # 「ファイル 'xaaaaa' を作成しています」という文字列から「xaaaaa」を抽出
    filename=${target//\'/}
    # mvコマンドでリネーム
    mv ${filename} ${prefix}${count}.txt
    count=$(expr ${count} + 1)
done

上記を理解する上で、splitコマンドを実行した場合の結果を知っておく必要があります。

splitコマンドの出力

splitコマンドのみの出力結果は以下のようになります。

split -a 5 -l 2 --verbose lists.txt
ファイル 'xaaaaa' を作成しています
ファイル 'xaaaab' を作成しています
ファイル 'xaaaac' を作成しています

ここで、-aオプションで5を指定しているため、suffix部分(aaaaaの部分)が5文字となっています。

また、アルファベットは26文字あるため、\(26^{5} = 11,881,376\)行まで対応でき、この程度あれば実用上問題ないと考えます。

動的なファイル分割

上記のシェルスクリプトの場合、決まった長さにしか分割できないため、指定した行数で分割できるようにカスタマイズします。

また、出力ファイル名のprefix(outの部分)と入力ファイル名も指定できるようにします。

上記を加味した実装例は以下のようになります。

#!/bin/bash

prefix=out
line=2
input=

while [ -n "$1" ]; do
    case "$1" in
        -p | --prefix )
            prefix="$2"
            shift
            shift
            ;;

        -l | --line )
            line="$2"
            shift
            shift
            ;;

        -i | --input )
            input="$2"
            shift
            shift
            ;;

        * )
            shift
            ;;
    esac
done

if [ -z "${input}" ] || [ ! -e ${input} ]; then
    echo Error: Input file does not exist. "(${input})"
    exit 1
fi

count=0
split -a 5 -l ${line} --verbose ${input} | while read dummy target others; do
    filename=${target//\'/}
    mv ${filename} ${prefix}${count}.txt
    count=$(expr ${count} + 1)
done

上記のシェルスクリプトのオプションは以下のようになります。

オプション内容
-p, --prefix出力ファイルのprefix
-l, --line分割時の行数
-i, --input入力ファイル名
オプション一覧

上記のシェルスクリプトをlinesplit.shとして保存した場合、以下のように利用します。

# ======
# 利用例
# ======

# 2行ずつに分割する場合
./linesplit.sh -l 2 -i lists.txt
out0.txt
out1.txt
out2.txt
# 3行ずつに分割&prefixをtmpにする場合
./linesplit.sh -l 3 -p tmp -i lists.txt
tmp0.txt
tmp1.txt

まとめ

今回は、splitコマンドを利用したテキストファイルの分割方法について解説しました。

他にもsplitコマンドにはオプションが用意されているため、用途に合わせて使い分けてみてください。

この記事がテキストファイルの分割時において、少しでも参考になれば幸いです。

スポンサードリンク



-プログラミング
-,