Windowsバッチファイル:CSVファイルの文字変換と列入れ替え

最近、一日一回、私のメールボックスにあるデータが登録されたCSVファイルが送られてくるようになったのですが、そのフォーマットに少し気に入らない部分があるので、それを書き換えてくれるバッチを作成してみました。

以下はメールで送られてくるCSVファイル(list.csv)のサンプルです。

【オリジナルのlist.csv】
add,full,num,lev
aaa,,0410-1,a
,bbb/,0410-2,b

これを以下のように書き換えたいと考えました。

【書き換え後(標準出力)】
add,full,num,lev
aaa,,0410-1,a
bbb,,0410-2,b

書き換えのポイントは以下の通りです。

1.2列目(full)の値の最後に”/”が付いていた場合は、それを削除する。
2.1.で書き換えたものを2列目(full)から1列目(add)に持っていく。

これだけのことですが、たくさん勉強することがありましたので、実際に作成したバッチを見ながら、処理を解説したいと思います。

バッチファイルのポイント解説

最終的に作成したバッチファイルは以下の通りですが、ポイントを解説していきます。

@echo off

setlocal ENABLEDELAYEDEXPANSION

for /f "tokens=1-4 delims=," %%a in (list.csv) do (
set line=%%a
if "%%d" == "" (
echo !line:/=!,,%%b,%%c
) else (
echo !line:/=!,%%b,%%c,%%d
)
)

endlocal

for /f “tokens=1-4 delims=,” %%a in (list.csv) do (

この5行目では、ファイル(list.csv)を1行1行読み込んでいます。
この時に、delims=,で”,”を区切り文字として4つのデータに分割し、それを
tokens=1-4と書くことで、%%a〜%%dの4つの変数にに入力しています。

set line=%%a

この6行目では、%%aに入力されているデータをlineという変数にセットしています。

if “%%d” == “” (

この7行目では、%%dに入力されているデータがあるかどうかで条件分岐させています。

【ポイント】なぜ %%d で分岐させているのか?
“,”を区切り文字として一行ずつ%%a〜%%dにデータを取り込んでいるので、普通に考えるとすべての行で%%dにデータがはいってきそうです。
(例えば、1行目は”lev”、2行目は”a”といった具合)

しかしバッチプログラムでは(空)のデータは%%aなどの変数にいれてくれず、次のデータが現れるまで同じ変数にデータをいれようとする仕様のようです。

したがって、list.csvの2〜3行目では%%a〜%%cまでしかデータが入ってこず、%%dが(空)になります。

あと、%%dを””で囲んでいる点にも注意が必要です。

echo !line:/=!,,%%b,%%c

この8行目では、!line:/=!の部分でlineに入っているデータに / が含まれていればそれを削除(つまり「/=(空)」と書いているイメージ)した上で、後続の”,,%%b,%%c”と一緒にechoで標準出力しています。

なお、この変換処理の為に、バッチの最初と最後に
setlocal ENABLEDELAYEDEXPANSION

endlocal
を書いています。

このあたりはおまじないと考えておけばいいようです。

echo !line:/=!,%%b,%%c,%%d

この10行目では”!line:/=!”に%%aのデータが入っているので、%%a,%%b,%%c,%%dと順番どおり出力しているだけになります。