2009年8月30日日曜日

CSVファイル内の特定項目に重複があるかチェックする


@echo off
:: *---------------------------------------------------------------------------
:: * WINDOWSバッチプログラム
:: * CSVファイル内の特定項目に重複があるかチェックする
:: * 
:: * 例として、各行の第2項目をチェック対象とする
:: * 第2項目の、カラム位置は(1オリジンで)12桁目から始まるものとする
:: * (11桁目がカンマとなる)
:: * 第2項目に英文字が使用されている場合は、
:: * 大文字・小文字どちらかに統一されているものとする
:: * 
:: * ■動かしてみたが、5000行で15秒以上かかって使い物にならない。
:: * 他に流用できそうな個所があるかもしれないので、残しておく。
:: * 
:: * ■ちなみに、Linux上で実装すると1行で完結する。
:: * sed 's/^.*,//' | sort | uniq --repeated --count
:: * そして、900000行を5秒程で処理できる………
:: * 
:: * ■↑パフォーマンスはPC依存ですよ
:: * 
:: *---------------------------------------------------------------------------


                            :: * ----------------------------------------------
                            :: * 変数初期化
                            :: * ----------------------------------------------
                            :: * 比較文字列バッファ
set PREV_STR=InitialDummyString
                            :: * 重複カウンタ
set /a V_COUNT_DUP=0
                            :: * 重複カウンタ合算。終了メッセージ切り分け用
set /a V_COUNT_DUP_TOTAL=0

                            :: * ----------------------------------------------
                            :: * 入力引数の有無確認
                            :: *   無ければ、プログラム説明を表示して終了
                            :: * ----------------------------------------------
if "" == "%1" goto SETSUMEI_DE_OWARI


                            :: * ----------------------------------------------
                            :: * ファイル内容のソート
                            :: *   各行の12桁目からの文字列が対象
                            :: * ----------------------------------------------
                            :: * 行の内容を分解して、
                            :: * 引数としてサブルーチンに渡す。
                            :: *   セパレータはカンマ
                            :: *   第1項目と第2項目を取得して
                            :: *   第1項目→%%L
                            :: *   第2項目→%%Mに取得するが、
                            :: *   サブルーチン渡すのは%%M(第2項目)のみ
                            :: * ----------------------------------------------
for /f "delims=, tokens=1-2"  %%L in ( 'sort /+12 %1' ) do call :SUB %%M
goto OK_NG_CHECK


                            :: * ----------------------------------------------
                            :: * サブルーチン
                            :: * ----------------------------------------------
:SUB
if "%PREV_STR%" NEQ "%*" (
    set PREV_STR=%*
    if %V_COUNT_DUP% GEQ 1 (
        echo 重複が切れました
        echo 重複項目名:%PREV_STR% 重複回数:%V_COUNT_DUP%
        set /a V_COUNT_DUP=0
    )
) else (
    echo 重複が継続中
    set /a V_COUNT_DUP+=1
    set /a V_COUNT_DUP_TOTAL+=1
)
goto EOF


                            :: * ----------------------------------------------
                            :: * プログラム説明を表示して終了
                            :: * ----------------------------------------------
:SETSUMEI_DE_OWARI
echo.
echo ここに説明を記述する
goto EXIT


                            :: * ----------------------------------------------
                            :: * チェック結果の判定
                            :: * ----------------------------------------------
:OK_NG_CHECK
                                :: * ------------------------------------------
                                :: * ファイル内最終行での重複を
                                :: * 取りこぼさない様に個別チェック
                                :: * ------------------------------------------
if %V_COUNT_DUP% GEQ 1 (
    echo 重複項目名:%PREV_STR% 重複回数:%V_COUNT_DUP%
)
                                :: * ------------------------------------------
                                :: * 結果判定と、メッセージ切り替え
                                :: * ------------------------------------------
if %V_COUNT_DUP_TOTAL% GEQ 1 (
    echo ▲上記のとおり、重複がありました▲▲▲
) else (
    echo △重複はありませんでした△△△△△△△
)


                            :: * ----------------------------------------------
                            :: * 終了
                            :: * ----------------------------------------------
:EXIT
echo.
echo 終了します、何かキーを押してください。
pause > NUL
echo on