IFステートメントの一般的な形式は次のとおりです。IF Value1 CompareOperator Value2 COMMAND
IFが実際に実行される前に、行をさまざまなコンポーネントに解析する必要があります。無効な構文につながる可能性のある多くのシナリオがあります。
いくつかの明白なものは、、、、のような特殊文字です:これらはのよう&
にエスケープするか|
、のように引用する必要があります。<
>
^&
"&"
<space>
、、、、、、などのトークン区切り文字はそれほど明白な問題では<tab>
あり;
ませ,
ん=
。これらもエスケープまたは引用する必要があります。たとえば<space>
、ユーザー入力としてプログラムから1行を取得します。`%input%を展開すると、行は次のようになります。
if /i { }=={/h} (
パーサーは、最初のエスケープされていない/引用符で囲まれていないトークン区切り文字でValue1を終了するため、Value1はであると見なし、それはCompareOperator{
の}
一部であると見なします。これにより、構文エラーが発生します。
もう1つの問題は、ユーザー入力の例のように、引用符の数が奇数の値です"
。
if /i {"}=={/h} (
見積もりはステートマシンです。引用が有効になると、パーサーは次の引用までのすべての文字が同じ文字列の一部であると見なします。したがって、パーサーはValue1が{"}=={/h} (
であると見なし、コマンドが不完全です-別の構文エラー。
部分的な解決策
あなたは次のようなことをすることができます
if /i "%input%"=="/h" ...
また、または;
、、などの入力で機能します。<space>
=
しかし、失敗する入力はまだたくさんあります。例:"
、"&"
。
フルソリューション
テストを行う唯一の確実な方法は、遅延拡張を有効にして、の!input!
代わりに使用することです%input%
。これが機能するのは、遅延拡張が行われる前に、パーサーがIFステートメントのさまざまなコンポーネントを検出するためです。
if /i !input!==/h (
パーサーはValue1を識別し!input!
、実行の直前に、値がユーザー入力に展開されます。この時点で、これ以上解析を行う必要はありません。IFステートメントは、展開された値全体が比較対象の値であることを「認識」しています。
これは、遅延拡張修正を含むコードの完全に機能するバージョンです。
@echo off
setlocal enableDelayedExpansion
:again
set /p input= ^>
if /i !input!==/h (
cls
echo /h
echo /r
echo /x
goto again
)
if /i !input!==/r (
cls
echo type blablafile.txt
goto again
)
if /i !input!==/x (
exit /b
)
echo !input!