「for」コマンドのつづきです。「for」コマンドを使うとファイル内の文字列を参照したり、置換したりすることもできます。
その他の関連しそうな記事
ファイル内の文字列の表示
まずは、ファイル内の文字列を読み込んで表示してみましょう。
読み込み用のサンプルファイルとして、「第9章」フォルダの中に「file.txt」ファイルを作ります。「file.txt」ファイルの中身は以下ような文字列を書き込みます。
a b c d 1 2a 3cb
a,b,c,d,1,2a,3cb
あ いい ううう ええええ
あ いい ううう ええええ
1行目はアルファベットと数字のスペース区切り。
2行目はスペースではなく、コンマ区切り。
3行目は日本語をスペース区切りで羅列。
4行目は全角スペース区切りを使っています。
このファイルの文字列を読み込み書き出すバッチファイル「read_write_1.bat」は「for」コマンドに「/f」オプションを付けて次のように書くことができます。「/f」オプションはファイルの内容に対してループ処理を行うオプションです。
1 2 3 4 5 |
@echo off for /f %%a in (file.txt) do ( echo %%a ) |
「in ( )」の括弧内に処理の対象となるファイル名を指定します。
指定したファイルに書かれた文字列が「%%a」に一行づつ入り、「do ( )」の括弧の中に書かれた内容をループ処理します。ここでは単純に、「%%a」に代入された文字をコマンドプロンプトに表示しています。
結果は以下のようになります。
1行目ははじめの文字「a」が「%%a」に入っています。このように「for」を使う場合は、一単語が「%%a」に代入されます。
2行目は行全体が表示されています。これは「,」では文字を区切ることができないため、行全体が一単語と認識されたからです。単語と単語の間を分けるのには「スペース」が必要です。
3行目の出力のように日本語も扱えます。
ただし、4行目の出力のように全角スペースも文字と判断されるため、全角スペースでは文字を区切ることができず、行全体が表示されています。
「file.txt」ファイルの1行目に関して、2単語以下の「b」、「c」…を取り出すことを考えましょう。
この場合は「tokens」オプションを用いてこのように書きます。以下のようなバッチファイル「read_write_2.bat」を作成しましょう。
1 2 3 4 5 |
@echo off for /f "tokens=1,2,3,4,5,6,7" %%a in (file.txt) do ( echo %%a %%b %%c %%d %%e %%f %%g ) |
実行すると、すべての文字列が表示されたと思います。
「tokens」オプションは「tokens=」の後に取り出したい文字列の番号を記入します。ここではすべて記入したいため、1から7までをコンマ区切りで記入しましたが、1と3番目の文字列が欲しい場合は”tokens=1,3″とします。
ちなみに、上の例のように指定する番号が連番であれば、「tokens=1-7」と書くこともできます。
「tokens」オプションをつけると、「%%b」、「%%c」…に2単語以下が代入されます。for文では「%%a」を指定しているので、アルファベット順の「%%b」、「%%c」が自動的に使用されたのです。「%%a」ではなく「%%i」を指定した場合だと、2単語以下には「%%j」、「%%k」…が使われます。
次は、「file.txt」ファイルの2行目のようなコンマに区切られた文字列を単語毎に取り出す場合を考えます。そのためには、「delims」オプションを「tokens」オプションに追加します。
1 2 3 4 5 |
@echo off for /f "tokens=1-7 delims=," %%a in (file.txt) do ( echo %%a %%c %%e ) |
「delims」オプションは区切りとなる記号を教えてやるのに使います。ここでは「,」を指定しています。上のバッチファイルの実行結果は以下のようになります。
分かりやすいように、バッチファイルの4行目の「echo」での出力を「%%a」,「%%c」,「%%e」の三つとしました。
2行目の出力について、「,」が消え一単語ずつが「%%a」,「%%b」…に代入されます。「echo」での出力は「%%a」, 「%%c」, 「%%e」ですので、a, c, 1が表示されています。
ただし、この状態では「,」のみが単語の区切り文字と認識されていて、スペースでは単語区切りができていません。したがって、1行目の表示が行全体の「a b c d 1 2a 3bc」となってしまっています。これは、全体が一つの単語として「%%a」に代入されたからです。
echoでの出力は「%%a,%%c,%%e」なので、表示は「a c 1」となって欲しいです。そのためには、「delims」オプションの指定に「スペース」も追加します。
1 2 3 4 5 |
@echo off for /f "tokens=1-7 delims=, " %%a in (file.txt) do ( echo %%a %%c %%e ) |
分かりにくいですが、「delims」オプションの「,」の後に「スペース」を追加しました。これで、スペースと「,」はともに区切り文字扱いとなったため、1行目と2行目が同じ出力になります。
以下、実行結果です。
同じように、全角スペースも区切り文字として指定しましょう。
1 2 3 4 5 |
@echo off for /f "tokens=1-7 delims= , " %%a in (file.txt) do ( echo %%a %%c %%e ) |
これも分かりにくいですが、「,」の前に全角スペースを追加しました。全角スペースは必ず「,」の前に入れてください。
実行して4行目をみると、期待通りの結果が得られたことが分かります。
ファイル内の文字列の置換
さて、この「/f」オプションを利用して、ファイル内のある文字列をすべて置換してしまうバッチファイルを作っていきましょう。
置換対象となる入力ファイル内を1行ずつ読み込んでいき、置換したい文字列があればそれを置換してから、出力ファイルに書き出していくといった方法です。
今回は、サンプルとして以下の文章を使います。ファイル「input.txt」を新たに作り、貼り付けてください。
The woman standing on the wing of the Boeing Stearman plane
was wearing dark glasses.
The plane flew under a bridge, and then low over the crowd.
The woman waved.
The crowd waved back.
The woman’s name is ‘Risa’.
まずは、この文章を一行ずつ読み込んで、コマンドプロンプト上に書き出してみます。バッチファイル「translate_1.bat」を作成し以下のプログラムを書きます。
1 2 3 4 5 |
@echo off for /f "delims=" %%a in (input.txt) do ( echo %%a ) |
前節で登場していた「/f」オプションを使ったfor文です。
ここで注目するのは「”delims=”」と区切り文字の指定をしていないことです。区切り文字がないということは、文章が区切られないので必ず「%%a」に一行分が丸々代入されます。
コマンドプロンプトで「translate_1.bat」打って実行して下さい。以下は実行結果です。
次に文字列の置換方法です。上の文章の「woman」を「girl」に置換してみましょう。
バッチファイルはこのようになります。
1 2 3 4 5 6 7 8 9 10 |
@echo off setlocal ENABLEDELAYEDEXPANSION for /f "delims=" %%a in (input.txt) do ( set line=%%a echo !line:woman=girl! ) endlocal |
見慣れないコマンドがたくさん登場しました。
まず、for文を挟んで登場する「setlocal ENABLEDELAYEDEXPANSION」と「endlocal」ですが、これは二つで一セットです。意味はここでは覚えなくてよいです。おまじないとして、文字列を置換するときはとにかくこれでfor文を挟み込むとだけ覚えておきましょう。自分でfor文を使った文字置換プログラムを作るときも、とにかく書いておけばオッケーです。
for文の中をみると、まず「set」コマンドで変数「line」の中に「%%a」を代入しています。これで、「line」には「input.txt」の文章が一行分入った状態になります。
次の「echo」コマンドの引数「!line:woman=girl!」ですが、これが変数「line」の中の「woman」という文字列を「girl」に書き換えるという指示です。このように、
1 |
![1行分の文字列]:[置き換えられる文字列]=[置き換えた後の文字列]! |
とすれば、[一行分の文字列]は[置き換えられる文字列]を[置き換えた後の文字列]に置換されて出力されます。「!」で囲むことに注意しましょう。
以下が実行結果です。
「woman」が「girl」に置換されています。
さらに、このバッチファイルをファイル出力するように書き換えます。
ファイル出力の場合は「!line:woman=girl!」の後に「>> 出力ファイル名」を書きます。
1 2 3 4 5 6 7 8 9 10 |
@echo off setlocal ENABLEDELAYEDEXPANSION for /f "delims=" %%a in (input.txt) do ( set line=%%a echo !line:woman=girl! >> output.txt ) endlocal |
これをコマンドプロンプト上で実行すれば、「output.txt」というファイルができ、その中に置換後の文章が記述してあると思います。
しかし、これで完成ではありません。もう一度、同じように実行してみてください。
これで二度実行しましたので、「output.txt」ファイルを開いて見てください。以下にファイル内を示します。
同じ文章が二回書れてしまっています。
これはファイルに出力するためのコマンド「>>」が、前のファイルを消さずに、追加でファイル出力するコマンドだからです。つまり、一度目の実行で書かれた内容はそのままにして、二度目の実行でその下にさらに文章が追記されてしまったということです。
これを回避するには、バッチファイルのはじめに既に出力ファイル「output.txt」がある場合は削除すればよいでしょう。第7章で登場した、「ファイルがあれば削除する」というif文を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 |
@echo off if exist output.txt del output.txt setlocal ENABLEDELAYEDEXPANSION for /f "delims=" %%a in (input.txt) do ( set line=%%a echo !line:woman=gril! >> output.txt ) endlocal |
3行目を「if exist」文に書き換えました。これで完成です。
第9章 まとめ
本章では前章に続いて「for」文を使ってできることを紹介しました。
そのメインがファイル内文字列の一括置換です。ファイル内文字列の一括置換を行う場面は多いかと思います。ファイル内容の操作ができる「/f」は使用頻度が高い重要なオプションですので、是非身に付けましょう。
【入門講義 第9章のまとめ】
- その1 ファイルの内容のループ処理には「/f」オプションを使用する。
- その2 for文の「tokens」と「delims」オプションで文字列の分割を行う。
- その3 「>> [ファイル名]」はファイルに追記するコマンド
なにか不明な点やうまくいかない場合は、「お問い合わせフォーム」からお気軽にお問い合わせ下さい。
次章では、「ラベル」について学びます。「ラベル」を導入するとプログラムのコード上で好きな場所に移動することができます。また、長くなって見づらいプログラムをスッキリと整理することができます。
echo !line:woman=gril! >> output.txt
の文の「girl」の文字列を変数で定義するにはどうすればよいですか?
下記のような感じにしたいです。
———————————————-
@echo off
if exist output.txt del output.txt
setlocal ENABLEDELAYEDEXPANSION
set _moji=girl
for /f “delims=” %%a in (input.txt) do (
set line=%%a
echo !line:woman=%_moji%! >> output.txt
)
endlocal
———————————————-
ご質問ありがとうございます。
n.t様が提示しているコードでうまくいきましたが、そちらでは何か問題があるのでしょうか?
はじめして質問します
a.txtにファイルのフルパスが一行ずつ
ならんでいます
あ
b
c アルファベットはフルパス自動で改行がはいっています
そのテキストにあるフルパスファイルを
まとめてムーブであるフォルダに移動するか 削除したいのです
両方の装飾しかたのバッチファイルを教えていただけませんでしょうか?
@echo off
setLocal EnableDelayedExpansion
for /f “tokens=* delims= ” %%a in (input.txt) do (
set /a N+=1
echo ^”del “%%a^”,>>output.txt
削除コマンドの装飾にこうやってみましたが・・うまくいきませんでした