IF 语句的一般形式为IF Value1 CompareOperator Value2 COMMAND
在实际执行 IF 之前,必须将该行解析为各种组件。有许多情况会导致语法无效。
一些明显的是特殊字符,如&
, |
, <
, >
: 这些必须像转义^&
或引用一样"&"
。
<space>
像, <tab>
, ;
, ,
, 和之类的标记分隔符不是那么明显的问题=
。这些也必须转义或引用。以您的程序中的一行<space>
作为用户输入为例。`%input% 展开后,行看起来
if /i { }=={/h} (
解析器在第一个未转义/未引用的标记分隔符处终止 Value1,因此它认为 Value1 是{
并且它认为它}
是 CompareOperator 的一部分。这会产生语法错误。
另一个问题是带有奇数引号的值,例如您的用户输入示例"
.
if /i {"}=={/h} (
行情是一个状态机。启用引用后,解析器认为直到下一个引号之前的所有字符都是同一字符串的一部分。所以解析器认为 Value1 是{"}=={/h} (
,并且命令不完整 - 另一个语法错误。
部分解决方案
你可以做类似的事情
if /i "%input%"=="/h" ...
它将与;
or <space>
, or=
等输入一起使用。
但是仍然有很多输入会失败。例如:"
, "&"
。
完整的解决方案
进行测试的唯一可靠方法是启用延迟扩展并!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!