如果我采取以下
Windows批处理代码段并运行它:
echo foo if 1 == 1 ( echo bar goto asdf :asdf echo baz ) else ( echo quux )
我期望的输出是:
foo bar baz
但是我得到:
foo bar baz quux
如果我注释了goto asdf行,它给出了我期望的输出.回声曲线不应该被引导出来,那么为什么goto的存在会导致这种情况呢?
更新:为什么值得,这是一个解决方法,正确地做了我原来的意图:
goto BEGIN :doit echo bar goto asdf :asdf echo baz goto :EOF :BEGIN echo foo if 1 == 1 ( call :doit ) else ( echo quux )
但是,这并不能解答我原来的问题.
CALL或GOTO的目标不应位于括号内的块语句中.可以做到这一点,但是如你所见,结果可能不会是你想要的.
整个IF(…)ELSE(…)构造被解析并加载到内存中,然后再处理它们.换句话说,它被逻辑地视为一行代码.解析后,CMD.EXE期待从IF / ELSE结构之后的下一行开始继续解析.
解析阶段后,复制命令从内存中执行.正确处理IF子句并正确跳过ELSE子句.但是在IF(true)子句中,您执行GOTO:asdf,因此CMD.EXE开始扫描标签.它从IF / ELSE的结尾开始,并扫描到文件的底部,循环回到顶端,并扫描直到找到标签.标签恰好在您的IF子句中,但标签扫描器对该细节无关.因此,当复杂命令从内存完成执行时,批处理从标签而不是从复合IF / ELSE的结尾继续.
因此,在这一点上,批处理器看到并执行接下来的几行
echo baz ) else ( echo quux )
巴兹回应了,也是如此.但是您可能会问:“为什么不”)else(和/或)生成语法错误,因为它们现在不平衡,不再作为较大IF语句的一部分解析?
这是因为如何处理.
如果遇到一个打开(活动的时间),那么)按照你的预期进行处理.
但是,如果解析器期望一个命令,并发现a)当没有活动打开(,那么)将被忽略,并且该行的其余部分上的所有字符都将被忽略!有效地,)现在作为一个REM语句.