お知らせ+活動記録+たわごと

HP と Twitter を補完するとともに、互いの密接な連携を図るため、本ブログを開設した。三位一体を目指す。情報提供、広報活動、教育・啓蒙活動の一環として、肩の力を抜き、冗長性を廃し、簡にして要を得た文章を書くよう心がける。
<< June 2017 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >>
 
MOBILE
qrcode
PROFILE
無料ブログ作成サービス JUGEM
 
FINDSTR 実行後の ERRORLEVEL に応じた条件分岐
Windows に標準で備わっているコマンドプロンプトはシェルに比べると非力だが、UNIX 系コマンドさえ導入すれば、そこそこ便利に使える。バッチファイルにおいて、文字列がテキストファイル中に存在するか否かで後続処理を変えるとき重宝する構文をここで紹介したい。

コマンドプロンプト用文字列検索コマンド FINDSTR は UNIX 標準の grep/egrep の機能を劣化させたようなコマンドであり、単純な正規表現しか使えない。FINDSTR は文字列を含む行を出力するとともに、文字列が見つかったら ERRORLEVEL=0、見つからなかったら ERRORLEVEL=1 という復帰コードを返す。しかし文字列が存在しようがしまいがエラーとは言い難く、文字列の有無を知るために %ERRORLEVEL% の値を調べるのには心理的抵抗がある。たとえば RETURNCODE とすべきではないか。いずれにせよ、長くて鬱陶しい復帰コード名だ。

FINDSTR と &&(論理積)または ||(論理和)とを組み合わせると、IF, ELSE, ELSE IF, %ERRORLEVEL% が不要となり、バッチファイル中の検索・条件分岐部分が実にすっきりする。たとえば、test.txt というテキストファイル中に
  1. 正規表現 (Regular expression) の文字列 reg_string1 が存在する、
  2. さもなければ正規表現の文字列 reg_string2 が存在する、
  3. いずれも存在しない、
という三通りの検索結果に応じて後続処理を切り換えるには、次のようにブロック化する:

FINDSTR /R /C:"reg_string1" test.txt >NUL 2>&1 && (
  .....
) || FINDSTR /R /C:"reg_string2" test.txt >NUL 2>&1 && (
  .....
) || (
  .....
)

/R は正規表現の文字列を探索するオプションである。FINDSTR は簡易正規表現しか扱えないという手抜き仕様に留まっているが、通常の目的には十分だろう。/C: は文字列中の空白が文字列同士の区切り文字とみなされないようにするオプションであり、">NUL 2>&1" はコマンドプロンプト窓が散らかるのを防ぐための呪文である。&& に続く (.....) ブロック内には検索に成功した場合 (ERRORLEVEL = 0)、|| に続く (.....) ブロック内にはヒットしなかった場合 (ERRORLEVEL = 1) の処理を記述する。ブロックの始まりと終わりを意味する "(" と ")" は必ずペアになっていなければならない。

reg_string1 が test.txt 中に存在しないときは、単に

FINDSTR /R /C:"reg_string1" test.txt >NUL 2>&1 || (
  .....
)

とするだけで済む。

通常の文字列 "string" を探索する際には、/R の代わりに /L を指定するか、

FIND "string" test.txt

を使う。オプション不要なところがありがたい。

コマンド実行後の && と || による条件分岐は広く認知されているとは言い難く、ネット情報はほとんど見かけない。呪文めいてはいるものの、頻用されてしかるべき便利な表現である。

なお FINDSTR と FIND では原則として Shift_JIS コードのファイルを処理するためのコマンドだが、ASCII 文字の検索に限定するならば、EUC や UTF-8 コードのファイルも扱えるようだ。

Windows 用 RIETAN-FP・VENUS 統合支援環境には、テキストファイル中に特定の文字列が含まれているか否かを調べてから後続処理を条件分岐するバッチファイルがいくつか含まれている。従来は FOR 文の実行結果を環境変数に代入し、その値を IF 文で参照するという、ややこしい手続きを踏んでいた。遅延展開せざるを得ない可能性がある環境変数の増加はできるだけ控えたい。

たとえば RIETAN.bat 中では、あらかじめ "MEP = 1" が hoge.lst 中に存在するか否かを

FOR /F "TOKENS=3 USEBACKQ" %%T IN (`FINDSTR /R /C:"^ *MEP = 1$" "%SAMPLE%.lst"`) DO SET MEP=%%T

という長い FOR 文を通じて変数 MEP に代入した後、

IF "%MEP%"=="1" (
  .....
)

という IF ブロックを実行するかどうかを判定していた。意味が理解しにくい上、冗長だ。同等の条件分岐を

FINDSTR /R /C:"^ *MEP = 1$" %SAMPLE%.lst >NUL 2>&1 && (
  .....
)

という簡潔な命令で実行できるのは感動的ですらある。次期配付ファイルでは、FINDSTR または FIBD コマンドでストレートに場合分けするよう全面的に書き換える予定である。
コメント
コメントする









 

(C) 2017 ブログ JUGEM Some Rights Reserved.