Windows批量转换在if块中不起作用

时间:2013-06-21 17:36:59

标签: windows batch-file

当我尝试在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的回答:Using parameters in batch files at DOS command line,但我遇到了一些麻烦。为什么会这样?

4 个答案:

答案 0 :(得分:12)

这是预期的行为,因为在解析行时会扩展%1,并且在一次传递中解析整个带括号的IF构造。因此,在解析新行之前,您无法看到SHIFT的结果,这在您离开括号内的块之后才会发生。

使用%var%扩展环境变量时会出现同样的问题。使用环境变量,您可以使用SETLOCAL EnableDelayedExpansion启用延迟展开,然后使用!var!来解决问题。但是没有任何类似的方法可以使用延迟扩展来扩展参数。

编辑2013-06-21 - 没有类似的方法,但有一种相对较慢的简单方法。

您可以使用CALL并将%加倍来强制重新排序该行。

@echo off

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


strong <编辑2016-07-15 code in Vladislav's answer是一种不好的做法,因为它意味着您可以在使用GOTO离开后在一段代码中跳回来。这根本行不通。 GOTO立即杀死任何已解析的代码块。你也可以把弗拉迪斯拉夫的代码写成:

@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所做的那样)在带括号的代码块中使用GOTO标签。

以下是做同样事情的更好(更简单且没有误导性)的方法:

@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

答案 1 :(得分:2)

实际上,如果阻止,你可以在外面执行转移:

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

:perform_shift
shift
echo "shifted"
goto:aftersift;


:end

答案 2 :(得分: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%

答案 3 :(得分:0)

要实现所需的目标,可以在移括号时使用附加的CALL

@echo off

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

示例运行:

>ex.bat /p HAI

/p
"shifted"
HAI