这是预期的行为,因为%1
在解析行时会展开,并且整个带括号的 IF 构造在一次传递中全部解析。因此,在解析新行之前,您无法看到 SHIFT 的结果,直到您离开带括号的块之后才会发生这种情况。
使用扩展环境变量时会发生同样的问题%var%
。使用环境变量,您可以通过启用延迟扩展来解决问题SETLOCAL EnableDelayedExpansion
,然后使用!var!
. 但是没有任何类似的方法可以使用延迟扩展来扩展参数。
编辑 2013-06-21 - 没有可比的方法,但有一种相对较慢的简单方法。
您可以通过使用 CALL 并将%
.
@echo off
if "%1"=="/p" (
echo %1
shift
echo "shifted"
call echo %%1
)
编辑 2016-07-15 Vladislav 答案中
的代码是一种不好的做法,因为这意味着您可以在使用 GOTO 离开后跳回代码块。那根本行不通。GOTO 立即杀死任何已解析的代码块。您不妨将 Vladislav 的代码编写为:
@echo off
if "%1"=="/p" (
goto :true
:true
echo "%1"
shift
echo shifted
echo "%1"
)
如果条件为 FALSE,则跳过整个块。如果条件为 TRUE,则 GOTO 立即终止该块,然后在 :true 标签处正常执行(无块上下文)。最后的额外)
内容被简单地忽略了。
请注意,您不能使用此构造添加 ELSE。以下没有给出预期的结果:
@echo off
if "%1"=="/p" (
goto :true
:true
echo "%1"
shift
echo shifted
echo "%1"
) else (
echo This will execute regardless whether arg1 is /p or not
)
如果为 FALSE,则仅执行 ELSE 块。如果为 TRUE,则执行顶部块并立即终止。代码的其余部分被执行,并且该) else (
行被忽略,因为)
如果解析器期望一个命令并且堆栈上没有活动的括号块,则作为 REM 起作用。
我强烈建议您永远不要像上面显示的那样(或 Vladislav 所做的)那样在带括号的代码块中转到标签。
下面是做同样事情的更好(更简单且不会误导)的方法:
@echo off
if not "%1"=="/p" goto :skip
echo "%1"
shift
echo shifted
echo "%1"
:skip
您可以使用一些额外的标签和 GOTO 来支持 IF/THEN/ELSE 概念
@echo off
if not "%1"=="/p" goto :notP
echo "%1"
shift
echo shifted
echo "%1"
goto :endIf
:notP
echo not /p
:endIf