Y子です。
どのご家庭でも毎日行う、外部データの読み込み。
テキストデータを1行ずつ取り込む作業は、朝食前にササっと終わらせたいものです。;p
その例を、今日は書いてみます。
【2021/04/13 21:00 コードの順番を入れ替え、見やすくしました】
#概要・用途
テキストファイルから1行ずつ読み込み、処理に使います。
たとえば、__「不要なファイルのリストを用意しておき、削除処理に使う」__のような用途を想定します。
#コード
##(1) 成功例
いくつか対策を盛り込んだ例です。
@echo off
rem 引数がない場合は終了する
if "%~1"=="" (
echo 引数がありません
pause
exit /b
)
rem 外部ファイル(引数から取得)
set str_file=%1
for /f "delims= eol=" %%a in (%str_file%) do (
echo %%a
)
pause
外部ファイルとして、記号がいっぱいのヤバそうなファイルを用意してみました。
これを取り込みます。
!"#$%&'()*+,-./0123456789:
;<=>?@ABCDEFGHIJKLMNOPQRSTU
VWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~ !"#$%&'()*+,
-./0123456789:;<=>?@ABCDEFG
HIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}
~
> read_extfile.bat test.txt
!"#$%&'()*+,-./0123456789:
;<=>?@ABCDEFGHIJKLMNOPQRSTU
VWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~ !"#$%&'()*+,
-./0123456789:;<=>?@ABCDEFG
HIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}
~
続行するには何かキーを押してください . . .
すべての行が出力されました。
なお、この例のバッチファイルは、外部ファイルのパスを引数で取得しています。
なので、バッチファイルに外部ファイルをマウスでドロップしても、同じ動作になります。
##(2) 説明
「/f
」はfor
文のオプションで、「トークンを代入する」という意味です。
変数%%a
に、テキストファイルから読み込んだ文字列(トークン)を格納するのに必要です。
なおトークンとは、「区切り文字で区切られた文字列」のことだそうです。
トークンの区切り文字(デリミタ)は、デフォルトでは半角スペース
とタブ
です。
また、コメント行は、デフォルトでは;
で始まる行で、トークンとして無視されます。
上記の例では、これらをデフォルトから変更しています。
"delims="
はデリミタの設定ですが、イコール(=
)の右辺が空なので、デリミタを定義なしとしています。
また、"eol="
はコメント行の設定ですが、これもイコール(=
)の右辺が空なので、行をどんな文字で始めても、コメント行になりません。
##(3) 失敗例1
デリミタやコメント行の設定をデフォルトのままにすると、以下のような動作になります。
@echo off
rem 引数がない場合は終了する
if "%~1"=="" (
echo 引数がありません
pause
exit /b
)
rem 外部ファイル(引数から取得)
set str_file=%1
for /f %%a in (%str_file%) do (
echo %%a
)
pause
for
文の"delims= eol="
を削除したので、デフォルトの下記設定になりました。
・デリミタは半角スペース
とタブ
・コメント行は;
始まり
これに、同じ外部ファイルを与えてみます。
> read_extfile_ng1.bat test.txt
!"#$%&'()*+,-./0123456789:
VWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~
-./0123456789:;<=>?@ABCDEFG
HIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}
~
続行するには何かキーを押してください . . .
成功例から、下記3か所が変わりました。
・1行目の、先頭の半角スペース
が消えた
・2行目(;
で始まる行)が、丸ごと消えた
・4行目(qrs
で始まる行)の、半角スペース
以降が消えた
つまり、このように動作したことになります。
・半角スペース
がデリミタ。
→先頭のスペースは無視される(1行目)
→途中のスペースでトークンが分割され、1件目だけ取得される(4行目)
・;
が先頭に来るとコメント行。
→コメント行は無視される(2行目)
##(4) 失敗例2
デリミタやコメント行の設定を復活させました。
加えて、遅延環境変数を展開したことで、別の問題が生じた例です。
@echo off
rem 引数がない場合は終了する
if "%~1"=="" (
echo 引数がありません
pause
exit /b
)
rem 遅延環境変数の展開を有効にする
setlocal enabledelayedexpansion
rem 外部ファイル(引数から取得)
set str_file=%1
for /f "delims= eol=" %%a in (%str_file%) do (
echo %%a
)
pause
> read_extfile_ng2.bat test3.txt
ECHO は <OFF> です。
;<=>?@ABCDEFGHIJKLMNOPQRSTU
VWXYZ[\]^_`abcdefghijklmnop
qrstuvwxyz{|}~ "#$%&'()*+,
-./0123456789:;<=>?@ABCDEFG
HIJKLMNOPQRSTUVWXYZ[\]^_`ab
cdefghijklmnopqrstuvwxyz{|}
~
続行するには何かキーを押してください . . .
成功例から、下記2か所が変わりました。
・1行目が、空文字列として出力された
・4行目(qrs
で始まる行)の、!
が消えた
遅延環境変数の展開を有効にすると、読み込んだトークン中の!
が意味を持ち、未定義の変数として解釈されて空文字列になったり、!
だけが消えたりします。
#注意
参考にしたサイトの一部には、「eol
は空にできないので、外部ファイルで使われない文字を入れて回避する」と書かれていましたが、わたしは空に設定できたようです。原因はわかりませんが、Windowsのバージョンなどに依存するのでしょうか。
#おわりに
外部ファイルが読み込めるようになりました。
また夢が広がりますね。
環境ごとに外部ファイルだけを変えることで、同じプログラムで複数の現場に対応できたりとか!
では!