forステートメントの最大の拡張機能ともいえるのが“/F”オプションによるファイル解析による繰り返し処理である。これは、括弧内で指定されたファイルの内容を解析して、それを変数に代入したうえで、コマンドを繰り返し実行する機能である。書式としては、
for /F "options" %%v in ( ファイルセット ) do コマンド
となる。このとき、[ファイルセット]で指定されたテキスト・ファイル(複数指定可能)が読み出され、その中にある各行がデリミタ(区切り子。これはoptionsで指定可能。デフォルトは「スペース」と「タブ」)で複数の“トークン(句、単語)”に分解される。
例えば、[ファイルセット]で指定されるファイルfile.txtの内容が以下のようなものだとする。各文字の間はタブ記号で区切られているものとする。
A<TAB>B<TAB>C<TAB>D<TAB>E<TAB>F<TAB>G
1<TAB>2<TAB>3<TAB>4<TAB>5<TAB>6<TAB>7
a<TAB>b<TAB>c<TAB>d<TAB>e<TAB>f<TAB>g
このとき、以下のステートメントをコマンド プロンプトから実行してみると
C:\>for /F %i in ( file.txt ) do echo %i
C:\>echo A
A ………1行目の先頭の文字だけが取り出される
C:\>echo 1
1 ………2行目の先頭の文字だけが取り出される
C:\>echo a
a ………3行目の先頭の文字だけが取り出される
このように、file.txtの各行の最初の部分が取り出されて変数に代入される(デフォルトでは、最初のパートのみを取り出すようになっている)。デリミタによる分解の後、各部分を指定するには、“/F”の後ろに“tokens=”でどのフィールドを取り出すかを指定する。いま解析対象となるファイルの中身が
Part01<D>Part02<D>Part03<D>……<D>PartX
となっているとすると(ここで“<D>”はデリミタ)、数値は、各パートを表し、例えば、5番目のパート(上の例でPart05)を取り出すには、“5”と指定すればよい。また、連続する範囲を指定する場合、“m-n”とハイフンで続けて2つの数値を指定する。例えば、3番目から6番目までのパート(Part03、Part04、Part05、Part06)をそれぞれ、個別の変数として取り出す場合には、“3-6”と指定する。この指定をカンマで区切って並べていけば、複数の変数が自動的に指定されて、それらに対して代入が行われる。また最後に“*”を置くと、残り部分が最後の変数にまとめて代入される。forコマンドでは変数は1つしか指定できないが、この場合には、指定された変数名に続くアルファベットが自動的に変数名として指定される。つまり、変数として“i”を指定した場合、その他の変数名として“j”、“k”、“l”、“m”……が使われることになる。
例えばfile.txtに対して以下のようなコマンドを実行してみよう。
C:\>for /F "tokens=1,2,3" %i in ( file.txt ) do echo %i %j %k %l
C:\>echo A B C %l
A B C %l ………3つの変数に値が取り出されたが、変数lは未定のまま
C:\>echo 1 2 3 %l
1 2 3 %l
C:\>echo a b c %l
a b c %l
このように、変数“i”に続いて変数“j”と変数“k”が自動的に用意され、そこに2つ目と3つ目のパートが代入される。しかしtokensでは4つ目以降のパートを指定していないため、変数“l”は未定義のままとなる。なおこのtokensの指定は、任意の順番で指定できるが、結果としてはパートの出現順に変数に定義される。つまり、“tokens=1,2,3”も“tokens=3,2,1”も“tokens=2,1,3”も同じ結果になる。また複数のパートをまとめて1つの変数に代入可能なのは、“*”が指定され、最後の変数に格納される場合のみである。ハイフンを使って“tokens=1-3”と指定しても、これは、3つの変数に最初の3つのパートが格納される。
オプションとして指定可能なのは、以下のようなものである(複数のオプションを指定する場合は、空白で区切って並べる)。
オプション | 意味 | |
---|---|---|
eol=c | 行末コメント開始文字をcにする。この文字以降は注釈として無視される | |
skip=n | ファイルの先頭からn行を無視する | |
delims=xxx | デリミタをxxxとする。複数文字の指定が可能。デフォルトはタブとスペース | |
tokens=x,y | どのパートを変数に代入してコマンド側に渡すかを指定する。 | |
usebackq | バッククォート(“`”、逆引用符)で囲まれた文字列をコマンドとして実行する | |
forの/F使用時に使用できるオプション |
かっこの中で指定するファイル名のセットの部分は、引用記号の付け方により解釈が変わる。さらにusebackqオプションによっても変化する。
この部分は、解析対象の「ファイル名」、「文字列」、「コマンド」の3つの解釈が可能である。「ファイル名」とは文字通り、この部分を解析する内容を含んだファイルの名前として受け取ることを意味する。「文字列」の場合には、これを直接解析する。最後の「コマンド」とは、これをいったんコマンド名とし、それを実行した結果を解析することになる。具体的に例を挙げてみよう。
■括弧内をファイル名とみなし、そのファイルの内容を解析する
C:\>for /F "tokens=1,3" %i in (file.txt) do @echo %i %j %k
A C %k
1 3 %k
a c %k
■括弧内を文字列として、それを直接解析する
C:\>for /F "tokens=1,3" %i in ("a b c d e") do @echo %i %j %k
a c %k
■かっこ内をコマンドとして実行し、その実行結果を解析する
C:\>for /F "tokens=1,3" %i in ('@echo a b c d e') do @echo %i %j %k
a c %k
もしくは
C:\>for /F "usebackq tokens=1,3" %i in (`@echo a b c d e`) do @echo %i %j %k
a c %k
この例で分かるように、かっこ内で文字列を囲まないか、ダブルクォート、シングルクォート、バッククォート記号のどれで囲むかによって解釈のされ方が違うわけである。この動作を表にまとめたのが以下のものである。
記号 | なし | ダブルクォート | シングルクォート | バッククォート | |
---|---|---|---|---|---|
usebackqなし | ファイル名 | 文字列 | コマンド | バッククォート記号を含むファイル名 | |
usebackqあり | ファイル名 | ファイル名 | 文字列 | コマンド | |
usebackqコマンドとファイル・セット指定の関係 |
まず、空白を含むファイル名を指定する場合には、これをダブルクォートで囲む必要があるため、かならず“usebackq”を指定しなければならない。なぜなら、ファイル・セットは、空白で区切って複数のファイルを指定するようになっているからである。
基本的には、usebackqを必ず指定することにして、ファイル名は必要に応じてダブルクォート記号で囲み、コマンドならばバッククォート、文字列ならシングルクォート記号で囲むという使い分けが安全だろう。
さて、この“/F”の使い方だが、例えばCSV形式のファイルのようなものを作って、それを元にコマンドを繰り返し実行するような場合に有用だろう。元のファイル名と変更したいファイル名を並べたファイルを作り、renコマンド(ファイル名を変更するコマンド)を実行すれば、大量のファイルの名前変更などが可能に行える。
またちょっとした応用として、タブ区切りファイルをカンマ区切りにしたり、CSVファイルの各フィールドの並べ替えといった用途にも利用できる。以下は、タブ区切りファイルをフィールドを逆順にしたカンマ区切りファイルに変換した例である。
C:\>more file.txt ………元のファイル
A B C D E F G
1 2 3 4 5 6 7
a b c d e f g
↑↑………上の各文字の間はタブ記号で区切られている
C:\>for /F "usebackq tokens=1-7" %a in ( file.txt ) do @echo %g,%f,%e,%d,%c,%b,%a >> rev.csv
C:\>more rev.csv
G,F,E,D,C,B,A
7,6,5,4,3,2,1
g,f,e,d,c,b,a
これを応用して、CSVファイルの一部のフィールドのみを取り出すといったことも可能だろう。また各種のログ・ファイルの簡単な整理などにも応用できるだろう。forステートメントの拡張は、単純な繰り返しだけでなく、このようなデータ処理もある程度は可能にしている。
Copyright© Digital Advantage Corp. All Rights Reserved.