treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

※https化しました。その影響でしばらくリンク切れなどがあるかもしれませんが徐々に修正していきます。 リンク切れなどのお気づきの点がございましたらコメントなどでご指摘いただけますと助かります。

バッチファイル内で記号を文字列として扱う際引っ掛かったこと

以前にバッチファイルで記号を扱うときにちょっとした不具合を引き起こしていたのですが、今回もバッチファイル内で記号を文字列として利用する際に問題があったので、実施した対処方法をご報告です。

バッチファイル内で記号を文字列として扱う

以前にはSSIDを設定するバッチファイルでパスフレーズに記号を使っていたせいでエラーが起きていました。

 

 blog.treedown.net

 

この時は.xmlファイル内で使用する文字列「<」が引っ掛かっていました。.xmlファイルだと「<」とか「>」は区切り文字として使われるので、誤認識したという結論でした。

今回バッチファイル内で「+」と「&」を使った文字列をバッチファイルの変数に代入するときに、変数にうまく代入されなかったのでその対処をやってみました。

文字列

バッチファイルは実際のバッチファイルではなく、テスト用のバッチファイルで検証しています。また対象の文字列は一例ですが、「abc+123&DE」という文字列です。

実際のバッチファイルではないのですが、テストバッチで以下のように文字列を変数に入れて使ってみます。

--------------------------------------------------------------
test.bat
--------------------------------------------------------------
@Echo off
set Char=abc+123&DE
echo %Char%
pause
set Char=
--------------------------------------------------------------

これを実行すると、

このようにエラーになってしまい、実際に実行したいコマンドである(ここではecho行が)正常に実行されず、その直前でエラーメッセージが表示されています。望んだ結果とは異なる形でバッチファイルが終了してしまいます。

記号の部分が文字列として扱われていないようなんですが、これまで対処方法が分かりませんでした。

例えば「echo "%Char%"」とか「echo '%Char%'」という具合にエラーになっているコマンド実行行の変数を囲ってみましたが、効果はありませんでした。

エラーメッセージからは「abc+123」と「&DE」が一行で認識していない感じがします。そもそもecho行で表示しているのは「abc+123」であり「&DE」が表示されていません。

エスケープ文字を使う

バッチファイルで文字列を扱う際に、「"」のような囲み文字を使うこともそうですが、変数に入れる際にエスケープ文字を使う、というのも基礎知識として覚えておくといいという話です。

今回で言えば、文字列「abc+123&DE」のうち「abc+123」は文字列として認識していますが、どうも「&」が間に入っていることで「DE」がコマンドとして認識しているような動きをしています。

これを「&」も文字列の一つですよと認識させるためにバッチファイル内で記号の前に「^」(キャレット記号、という)を加えます。これをエスケープ文字といいます。

今回で言えば「&」はコマンドの区切り文字として機能する記号となっているため、この動作を「^」を付加して「^&」と記述することで、コマンドの区切り文字でなくただの文字列の中の記号、として取り扱うことができます。

実際に使ってみる

文字列「abc+123&DE」を変数に入れる時、以下のように書き換えます。

abc+123^&DE

このように特殊記号の前に「^」という文字が必要になるわけです。

早速やってみたのですが、

あれ?「^」で文字列にしたのに、まだ「DE」はコマンドだとメッセージが表示されています。

ただ、echo行の後ろにメッセージが表示されるようになりました。つまり。

「^」で文字列にする前は、set行で変数に代入するときに「DE」がコマンドと誤認識

「^」で文字列にした後は、echo行で実際に文字列表示したあとに「DE」がコマンドと誤認識

という動作をしています。

コマンド実行行で変数を「"」で囲う

set行で「^」によ「&」が文字列として扱われるようになったのですが、今度はコマンド実行の際に「&」以降がコマンドとして認識するようになっています。

これは、

echo %Char%

にて、変数として使うとき、

echo "%Char%"

とすることで解決できました。

実際のバッチファイルです。

--------------------------------------------------------------
test.bat
--------------------------------------------------------------
@Echo off
set Char=abc+123^&DE
echo "%Char%"
pause
set Char=
--------------------------------------------------------------

エスケープ文字「^」で対象の記号を文字列の文字として認識させ、実際のコマンド実行において使う変数は、"%Char%"という具合に「"」ダブルコーテーションで囲む必要がある、という結論でした。

これで実行すると、

エラーメッセージが表示されることなく、変数に代入した「abc+123&DE」という文字列がechoで表示されるようになっています。

echoで表示されるようになったということは、この使い方で他のコマンド実行の引数としてこの表記の変数が利用可能になっている、ということが言えます。

エスケープ文字が必要になる記号

今回のように、変数に入れて文字列として使うときにエスケープ文字が必要になる記号を記述します。

  • 「&」はコマンド区切りに使われるので、「^&」と記述する。
  • 「|」はコマンドのパイプシンボルなので「^|」と記述する。
  • 「<」はコマンドへの読み込みに使うリダイレクトなので「^<」と記述する
  • 「>」はコマンドからの書き出しに使うリダイレクトなので「^>」と記述する。
  • 「^」はエスケープ文字そのものなので「^^」と記述する。
  • 「%」は変数に使う文字列なので「%%」と記述する。
  • 「!」は遅延環境変数というものの展開に使う文字なので「^!」と記述する。
  • 「"」は文字の囲みとして使われるので「^"」と記述する。
  • 「(」はコマンドのグループや条件指定の際に使われるので「^(」と記述する。
  • 「)」はコマンドのグループや条件指定の際に使われるので「^)」と記述する。
  • 「\」はディレクトリパスの区切り文字なので、「\\」と記述する。

おそらくこれで概ね網羅できていると思います。

これらの対象となる記号は特殊文字の前に「^」を付ける、そのうえで変数(文字列)全体を " で囲む、というルールをバッチファイル作成時に注意して文字列を取り扱うようにします。