0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

バッチファイルで外部ファイルから1行ずつ取得する

Last updated at Posted at 2021-04-13

Y子です。
どのご家庭でも毎日行う、外部データの読み込み。
テキストデータを1行ずつ取り込む作業は、朝食前にササっと終わらせたいものです。;p
その例を、今日は書いてみます。

【2021/04/13 21:00 コードの順番を入れ替え、見やすくしました】

#概要・用途
テキストファイルから1行ずつ読み込み、処理に使います。
たとえば、__「不要なファイルのリストを用意しておき、削除処理に使う」__のような用途を想定します。

#コード
##(1) 成功例
いくつか対策を盛り込んだ例です。

read_extfile.bat
@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

外部ファイルとして、記号がいっぱいのヤバそうなファイルを用意してみました。
これを取り込みます。

test.txt
 !"#$%&'()*+,-./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
デリミタやコメント行の設定をデフォルトのままにすると、以下のような動作になります。

read_extfile_ng1.bat
@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
デリミタやコメント行の設定を復活させました。
加えて、遅延環境変数を展開したことで、別の問題が生じた例です。

read_extfile_ng2.bat
@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のバージョンなどに依存するのでしょうか。

#おわりに
外部ファイルが読み込めるようになりました。
また夢が広がりますね。
環境ごとに外部ファイルだけを変えることで、同じプログラムで複数の現場に対応できたりとか!

では!

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?