目次
ファイル内の重複している行を削除する
ここでは、ファイル内の重複している行を削除して、ファイルを作り直すバッチファイルを作成していきます。例えば、以下のようなファイル「duplication.txt」があったとしましょう。
ファイルの内容をよく見ると、「file5」と「file3」という行が二回登場しており、行の重複があることが分かります。この重複している行をバッチファイルを使って削除しましょう。
多少複雑ですが、いきなりバッチファイルを示します(以下のプログラム)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
@echo off rem 「new.txt」ファイルが存在していれば、削除する if exist new.txt del new.txt rem for文内で変数を変化させるためのもの setlocal enabledelayedexpansion rem 変数「n」に0を代入 rem 以下のforループで「duplication.txt」ファイルの何行目まで読み込んだかが入る set n=0 rem 「duplication.txt」ファイルを1行ずつ読み込む for /f %%a in (duplication.txt) do ( rem 変数「n」に1を足す set /a n=!n!+1 rem 変数「m」に0を代入 rem 以下のforループで「duplication.txt」ファイルの何行目まで読み込んだかが入る set m=0 rem 変数「write」に1を代入 rem 内容が重複しているかどうかの情報が入る set write=1 rem 「duplication.txt」ファイルを1行ずつ読み込む for /f %%b in (duplication.txt) do ( rem 変数「n」に1を足す set /a m=!m!+1 rem ループ内で、読み込んだ場所までに重複している行があれば、「write」に0を代入 if !m! lss !n! ( if %%a == %%b ( set write=0 ) ) ) rem 重複行がなければ(変数「write=1」)、「new.txt」ファイルに書き出す if !write! equ 1 echo %%a >> new.txt ) rem for文内で変数を変化させるためのもの endlocal |
このプログラムを順に説明していきましょう。4行目では、「new.txt」ファイルが存在していればファイルを削除します。この「new.txt」ファイルは「duplication.txt」ファイルの重複行を削除したものが出力されるファイルです。詳しくは「ファイルが存在している場合にのみコマンドを実行する -やりたいことから検索-」をご覧下さい。
7行目はプログラム中のforループ文で変数の値が変化するようにするためのコマンドです。詳しくは、「forループの中で値を変化させる -やりたいことから検索-」をご覧下さい。
11行目では、変数「n」に0を代入しています。この変数「n」はforループで「duplication.txt」ファイルの何行目まで読み込んだかが入ることになります。
14行目からは、forループが始まっており、ここで重複行が存在するファイル「duplication.txt」の内容を上から一行ずつ読んでいきます。ファイル内容の読み込みについては、「ファイルから文字列を読み込む -やりたいことから検索-」を参照して下さい。読み込んだ行は「%%a」に入ります。
17行目では、11行目で0を代入した変数「n」の値をプラス1しています。これは「%%a」にはn行目の文字列が代入されていることを記録するためです。
そして、21行目でも変数「m」を導入しています。これも「duplication.txt」ファイルの何行目まで読み込んだかという情報が入るのですが、後にまた出てきますのでそのときに説明します。
25行目の変数「write」は重要です。この「write」は、重複を除いた新しくできるファイルに「%%a」に代入してある文字列を書き込むかどうか判断するためのものです。もし、「write」が1の場合、重複行は無いと判断され新しくできるファイルに書き込まれますが、逆に0の場合は重複行があったと判断され新しくできるファイルに書き込まれません。ここでは、「write」に1を初期値として代入していますが、以下のforループ文で重複行が見つかると変数の中身は0に置き換わります。
28行目は再び「duplication.txt」ファイルをforループで一行ずつ読んでいきます。ここで、一度目のforループの中にさらにforループを作っていることに注意してください。読み込んだ行は「%%b」に入ります。
31行目では、21行目で0を代入した変数「m」の値をプラス1しています。これは「%%b」にはm行目の文字列が代入されていることを記録するためです。
34~36行目のif文で、重複があるかを判断しています。文字列「%%a」に対して、その文字列「%%a」がある行よりも上部に同じ文字列の行があれば、変数「write」を0にセットします。「write」が0にセットされた行は重複を除いた新しくできるファイルには書き込まれません。この探索には「%%b」を使ってもう一度ファイル内容を上からチェックしている点に注目して下さい。if文や数値同士の比較に関しては「バッチファイルで数値を比較する -やりたいことから検索-」が参考になります。
そして、ようやく40行目で新たなファイル「new.txt」に「%%a」を書き出しています。ただし、「write」に0が入っていた場合は書き出しは行われません。0が入っていた場合は、35行目で上に同じ行があったと判断されたからです。
結構複雑なバッチファイルになりましたが、バッチファイルで重複行を取り除くことができました。以下には、上記のプログラムと全く同じですが、コメントを省略したものを載せておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@echo off if exist new.txt del new.txt setlocal enabledelayedexpansion set n=0 for /f %%a in (duplication.txt) do ( set /a n=!n!+1 set m=0 set write=1 for /f %%b in (duplication.txt) do ( set /a m=!m!+1 if !m! lss !n! ( if %%a == %%b ( set write=0 ) ) ) if !write! equ 1 echo %%a >> new.txt ) endlocal |
どうでしょうか?そんなにコードは多くないと感じてくれればよいのですが… 分かりにくかった場合は「お問い合わせ」から遠慮なくご質問下さい。