13

当我尝试在块SHIFT内使用时,IF我看到了一些意想不到的结果。使用这个:

@echo off

if "%1"=="/p" (
    echo %1
    shift
    echo "shifted"
    echo %1
)

我得到以下信息:

C:\>ex.bat /p HAI
/p
"shifted"
/p

但是,当我使用此代码时:

@echo off

echo %1
shift
echo "shifted"
echo %1

我明白了:

C:\>ex.bat /p HAI
/p
"shifted"
HAI

我需要第二个输出,但在一个逻辑块中,所以我可以循环它。我试图在这里实现类似于 Jon 的回答:在 DOS 命令行中使用批处理文件中的参数,但我遇到了一些麻烦。为什么会这样?

4

4 回答 4

14

这是预期的行为,因为%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
于 2013-06-21T18:06:24.667 回答
2

实际上,您可以在 if 块之外执行移位:

@echo off
if "%1"=="/p" (
    echo "%1"
    goto:perform_shift;
:aftersift
    echo "%1"
)
goto:end;

:perform_shift
shift
echo "shifted"
goto:aftersift;


:end
于 2014-10-23T13:30:21.900 回答
0

移位命令在块内部没有立即影响,但在外部。

假设您想将参数读取为键值对:

:Parse
if "%1" equ "/p" (
    set P=%2
    shift
    shift
)
if "%1" equ "/q" (
    set Q=%2
    shift
    shift
)
if "%1" neq "" goto Parse
echo P: %P%
echo Q: %Q%
于 2018-06-16T08:42:55.550 回答
0

为了实现你想要的,你可以CALL在括号中移动时使用额外的它:

@echo off

if "%1"=="/p" (
    echo %1
    shift
    echo "shifted"
    call echo %%1
)

示例运行:

>ex.bat /p HAI

/p
"shifted"
HAI
于 2020-11-09T14:59:21.167 回答