†DOSとバッチとスクリプト†

FORループによる文字列分解

作成開始日 2025.03.22
最終更新日

for文は本来ループ制御のための構文だが、バッチではしばしば文字列操作に使用される。
構文:for /f "usebackq tokens=取出項目 delims=区切文字" %%a in (文字列) do 命令
用例:for /f "usebackq tokens=2 delims=x." %%a in ("index01.dat") do echo %%a
基本的な考え方は、文字列を複数の部分に分割して、必要な部分のみを取り出す、というもの。分割の基本はホワイトスペース(半角スペースやタブ)で、例えば「This is a pen.」ならば「This」「is」「a」「pen.」の4つの要素に分解される。分解された要素から必要な要素を取り出して使用する。例えば、「a」(1つ)が必要な情報ならば3番目の項目を指定する。

区切り文字はホワイトスペースだけでなく、必要に応じて任意の文字を指定することができる。たとえば、「index01.dat」という文字列から、「01」の部分だけを取り出すには、「x」と「.」を区切り文字として、文字列を「inde」「01」「dat」のように3つの部分に分解して、2番目の項目だけを取り出せばよい(上記用例参照)。

for文の細かな構文解説は割愛して、以下ではキモとなるパラメータのみを説明する。

パラメータパラメータの意味パラメータの指定方法
文字列 処理対象の文字列を指定する
括りなし:ファイル名例)in (myfile.txt)
""で括る:生の文字列例)in ("That is a cat.")
''で括る:環境変数の中身例)in ('%st%')
``で括る:コマンドの実行結果例)in (`dir *.dat`)
区切文字 分割の区切りとなる文字を指定する delimsを指定しなければホワイトスペース
別の文字を区切り文字にするときは「delims=文字」で指定する
区切り文字は複数指定可能で「delmis=,.:」などのように並べて指定する
取出項目 何番目の項目を取り出すかを指定する 取り出す項目番号を「tokens=番号」で指定する(先頭は1)
取り出す項目は複数指定することも可能
 tokens=* 全項目を取り出す
 tokens=番号,番号,番号… 取り出す項目の番号を列挙
 tokens=開始番号-終了番号 取り出す項目の番号の範囲を指定
取り出された項目は、%%aから順に%%b、%%c、%%d…に代入される
代入は%%aからでなくとも良いが、%%aに固定する方が混乱がない

【参考】「文字列」としてファイル名やコマンドの実行結果を指定した場合、複数行の文字列が処理対象になる可能性がある。と言うより、複数行を順次処理するからこそのfor文で、ここで扱っているような文字列の操作は、for文の副次的な機能に過ぎない。

サンプル:ファイル名の一括リネーム

コマンドラインでRENとワイルドカード(*?)を使った一括リネームは、制限が多くて使い物にならない。たとえば、「index01.dat」「index02.dat」「index03.dat」…というファイル名を「01.dat」「02.dat」「03.dat」…とリネームしたい場合;
REN index??.dat ??.dat	←正常に機能しない例
では正常に機能しない(全て「in.dat」となり、ファイル名重複でエラーになる)。このような場合には、FOR文を使ってファイル名を分解して、新しいファイル名を生成すればよい。
FOR %%f in (index??.dat) DO (
FOR /f "usebackq tokens=2 delims=x" %%a in ('%%f') DO ECHO REN %%f %%a
)
なお、ここではファイル名が一定の文字数/フォーマットに統一性されているので、文字列変数の編集機能である「:~」を使う方が簡単かもしれない。しかし、不定フォーマットから規則性を見出して加工する場合は、こちらの方が柔軟性が高い。

【参考】この例ではREN命令を直接実行するのではなく、REN命令を画面に表示するに留めている。これは、ループによるリネームが二重実行されることがあるため。ここでは、外側のフィルターが「index??.dat」で、リネーム後のファイル名と被らないので二重実行は起きないが、たとえば「*.dat」や「*.*」をフィルターとした場合は、リネーム後のファイル名も引っ掛かって二重実行されることがある。そこで、命令をECHOするだけに留めた。使用するときは適当なバッチファイルにリダイレクトすればよい。


【DOSとバッチとスクリプト目次】 【ホーム】