Linux環境でよく使われる「CSVファイルを1行ずつ読み込んで、カンマ区切りで要素を分解して処理する(while read 構文)」を、Windowsのバッチファイル(.bat)で再現する方法です。
1. 元にするLinux(Bash)のコード
まずは、今回Windows版に移植したい元ネタのコードを確認しておきましょう。
Bash
while IFS=, read -r -a HAIRETSU; do
# 配列の各要素にアクセスして処理を記述
echo "第1フィールド: ${HAIRETSU[0]}"
echo "第2フィールド: ${HAIRETSU[1]}"
done < input.csv
カンマ(,)を区切り文字(IFS)に指定して、行を配列 HAIRETSU に格納していく定番の書き方ですね。
これをWindowsバッチでやろうとすると……実はバッチファイルには「本当の意味での配列変数」が存在しません。 そのため、ちょっとした「バッチ特有のコツ」が必要になります。
2. Windowsバッチ版の完成コード
結論から言うと、Windowsでは FOR /F コマンドを使うのが正解です。完成したコードがこちら!
DOS
@echo off
chcp 65001 > nul
setlocal enabledelayedexpansion
:: 読み込むCSVファイルを指定
set "INPUT_FILE=input.csv"
:: ファイルが存在しない場合はエラー終了
if not exist "%INPUT_FILE%" (
echo エラー: %INPUT_FILE% が見つかりません。
exit /b 1
)
:: FOR文でファイルを1行ずつ読み込み、カンマ(,)で分割
for /f "usebackq tokens=1,2 delims=," %%a in ("%INPUT_FILE%") do (
:: %%a が第1フィールド、%%b が第2フィールドに対応
set "FIELD1=%%a"
set "FIELD2=%%b"
:: ここに各要素を使った処理を記述
echo 第1フィールド: !FIELD1!
echo 第2フィールド: !FIELD2!
)
endlocal
pause
3. コードの解説(ここがポイント!)
Linux版からWindows版へ移植するにあたり、重要なポイントを3つに絞って解説します。
① 配列の代わりは「アルファベット順の変数」
バッチファイルでは tokens=1,2 delims=, というオプションを使います。
-
delims=,:カンマで区切るよ!という指定(BashのIFS=,) -
tokens=1,2:1番目と2番目の要素を取り出すよ!という指定
ここで基準となる変数を %%a に設定すると、自動的に %%b に2番目の要素が割り当てられます。(3番目があれば %%c になります)。 これがBashでいう ${HAIRETSU[0]} や ${HAIRETSU[1]} の代わりになります。
② ループ内の変数表示は % ではなく !
バッチファイルの最大の罠がここです。 通常のバッチでは変数を %FIELD1% のように囲みますが、FOR文(ループ)の中で中身がどんどん変わる変数を扱うときは、!FIELD1! のように !(びっくりマーク)で囲む必要があります。 これを使うために、冒頭で setlocal enabledelayedexpansion(遅延環境変数の有効化)というおまじないを書いています。
③ 文字化け対策の chcp 65001
もし読み込むCSVファイルが「UTF-8」で保存されている場合、Windowsバッチは高確率で文字化けします。 冒頭の chcp 65001 > nul は、バッチの文字コードを一時的にUTF-8に変更するコマンドです。これを入れておけば日本語が含まれるCSVでも安心です!(※CSVがShift-JISの場合は、この行を削除してくださいね)
まとめ
Linuxの while read は、Windowsバッチでは FOR /F "tokens=... delims=..." に化けます。
ちょっと癖のあるWindowsバッチですが、このパターンさえ覚えてしまえばCSVパース(解析)の自動化タスクも怖くありません。サーバーの移行作業や、クロスプラットフォームでのスクリプト運用の参考にしてみてください!
※おまけ
自動で変数が増えていく仕組み
FOR /F 文の中で指定する %%a は、あくまで「スタート地点の文字」という扱いになります。
コードの中で tokens=1,2(1番目と2番目の要素を取る)と指定した場合、バッチファイルは裏側で次のように自動割り当てを行います。
-
1番目の要素 = 指定した
%%aに入る -
2番目の要素 = アルファベット順で次の
%%bに自動で入る
もしこれが tokens=1,2,3,4 であれば、コードに書いていなくても %%a、%%b、%%c、%%d の4つの変数が自動的に使えるようになります。
⚠️ 使うときの注意点(バッチの罠)
この仕組みがあるため、バッチファイルを書くときは以下の2点に注意する必要があります。
① 大文字と小文字は区別される
スタート地点を小文字の %%a にした場合、自動生成されるのも小文字の %%b です。大文字で %%B と書くと別物とみなされて動かなくなります。
② アルファベットの「追い越し」に注意
もし tokens の数が多くて、変数名が %%z を超えてしまうと、それ以降の要素は正しく処理できなくなります。 また、スタート地点を %%x などにしてしまうと、%%x, %%y, %%z の3つまでしか自動生成できません。そのため、基本的にはスタート地点を %%a や %%i などの若いアルファベットにしておくのが鉄則です。
もし「変数名が自動で変わるのが気持ち悪い」ときは?
%%b や %%c をそのままコードの中で何度も使うと、どれが何のデータか分かりにくくなってしまいますよね。
そのため、ブログ風記事のコードでもやっていたように、ループの先頭で分かりやすい名前の変数にコピーしてあげるのが、バッチファイルを綺麗に書くコツです。
:: %%a と %%b を、分かりやすい変数名に入れ直す
set "FIELD1=%%a"
set "FIELD2=%%b"
:: 以降の処理は、この分かりやすい変数名を使う
echo 第1フィールドは !FIELD1! です
このように、%%b は「データを取り出すためだけの使い捨ての窓口」として割り切って使うと、スクリプトがすっきりして読みやすくなりますよ!
