(Windows 批处理)如果块中的 Goto 行为非常奇怪 [英] (Windows batch) Goto within if block behaves very strangely

查看:27
本文介绍了(Windows 批处理)如果块中的 Goto 行为非常奇怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用以下 Windows 批处理代码片段并运行它:

If I take the following Windows batch code snippet and run it:

echo foo
if 1 == 1 (
    echo bar
    goto asdf
    :asdf
    echo baz
) else (
    echo quux
)

我期望的输出是:

foo
bar
baz

但我得到:

foo
bar
baz
quux

如果我注释掉 goto asdf 行,它会给出我期望的输出.echo quux 行不应该被执行,那么为什么 goto 的存在会导致这种情况发生?

If I comment out the goto asdf line, it gives the output I expect. The echo quux line should never be exectuted, so why is the existence of the goto causing that to happen?

更新:就其价值而言,这里有一个正确执行我最初打算的解决方法:

UPDATE: For what it's worth, here's a workaround that correctly does what I originally intended:

goto BEGIN

:doit
    echo bar
    goto asdf
    :asdf
    echo baz
    goto :EOF

:BEGIN

echo foo
if 1 == 1 (
    call :doit
) else (
    echo quux
)

然而,这并没有回答我最初的问题.

However, this doesn't answer my original question.

推荐答案

CALL 或 GOTO 的目标永远不应在括号内的块语句内.可以做到,但正如您所见,结果可能不是您想要的.

The target of a CALL or GOTO should never be inside a block statement within parentheses. It can be done, but as you see, the results are probably not going to be what you want.

整个 IF (...) ELSE (...) 构造在处理任何一个之前都会被解析并加载到内存中.换句话说,它在逻辑上被视为一行代码.解析后,CMD.EXE 期望从 IF/ELSE 构造之后的下一行开始继续解析.

The entire IF (...) ELSE (...) construct is parsed and loaded into memory before any of it is processed. In other-words, it is logically treated as one line of code. After it is parsed, CMD.EXE is expecting to resume parsing starting with the next line after the IF/ELSE construct.

在解析阶段之后,从内存中执行复杂的命令.IF 子句处理正确,ELSE 子句正确跳过.但是在 IF (true) 子句中,您执行了 GOTO :asdf,因此 CMD.EXE dutifly 开始扫描标签.它从 IF/ELSE 的末尾开始,扫描到文件底部,循环回到顶部,一直扫描直到找到标签.标签恰好在您的 IF 子句中,但标签扫描仪对该细节一无所知.因此,当复杂命令从内存中执行完毕时,批处理会从标签而不是从复杂 IF/ELSE 的末尾恢复.

After the parse phase, the complex command is executed from memory. The IF clause is processed properly and the ELSE clause is skipped properly. BUT within the IF (true) clause, you perform a GOTO :asdf, so CMD.EXE dutifly begins scanning for the label. It starts at the end of the IF/ELSE and scans to the bottom of the file, loops back to the top, and scans until it finds the label. The label happens to be within your IF clause, but the label scanner knows nothing about that detail. So when the complex command finishes executing from memory, batch processing resumes from the label instead of from the end of the complex IF/ELSE.

所以此时批处理器看到并执行接下来的几行

So at this point the batch processor sees and executes the next few lines

    echo baz
) else (
    echo quux
)

baz 得到了回应,quux 也是如此.但是您可能会问,为什么 ) else ( 和/或 ) 不会产生语法错误,因为它们现在不平衡并且不再被解析为更大的 IF 的一部分声明?

baz is echoed, and so is quux. But you might ask, "Why doesn't ) else ( and/or ) generate a syntax error since they are now unbalanced and no longer parsed as part of the larger IF statement?

那是因为 ) 的处理方式.

That is because of how ) is handled.

如果在遇到 ) 时有一个打开的 ( 处于活动状态,那么 ) 会按照您的预期进行处理.

If there is an open ( active when ) is encountered, then the ) is processed as you would expect.

但是如果解析器在等待一个命令并且在没有活动的 open ( 时找到一个 ),则忽略 )并且该行其余部分的所有字符都将被忽略!实际上,) 现在用作 REM 语句.

But if the parser is expecting a command and finds a ) when there is not an active open (, then the ) is ignored and all characters on the remainder of the line are ignored! Effectively the ) is now functioning as a REM statement.

这篇关于(Windows 批处理)如果块中的 Goto 行为非常奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆