带分支的批处理文件 - if语句的替代方法

时间:2014-06-11 10:26:53

标签: batch-file if-statement

我有一个批处理文件接受操作模式作为参数并根据它按特定顺序运行几个命令,我想知道除了有大量的IF语句之外还有另一种处理这个批处理文件的方法吗? / p>

这不是真正的代码 - 仅显示流程

Get MODE as Parameter
If MODE=TYPE1 or MODE=TYPE2 then
    Run Command A
endif

If MODE=TYPE1 or MODE=TYPE3 then
    Run Command B
endif

If MODE=TYPE3 then
    Run Command C
endif

3 个答案:

答案 0 :(得分:2)

@echo off
    setlocal enableextensions

    set "MODE=%~1"
    set "WHENMODE=call :testCase "%MODE%" "

    %WHENMODE% TYPE1 TYPE2 && (
        echo Run command A
    )

    %WHENMODE% TYPE1 TYPE3 && (
        echo Run command B
    )

    %WHENMODE% TYPE3 && (
        echo Run command C
    )

    endlocal
    exit /b

:testCase value test1 test2 ... testn
    if "%~2"==""    exit /b 1
    if "%~1"=="%~2" exit /b 0
    shift /2 & goto %0

%WHENMODE%定义只是美学。没有装饰的相同代码

@echo off
    setlocal enableextensions

    set "MODE=%~1"

    call :testCase "%MODE%" TYPE1 TYPE2 && echo Run command A
    call :testCase "%MODE%" TYPE1 TYPE3 && echo Run command B
    call :testCase "%MODE%" TYPE3       && echo Run command C

    endlocal
    exit /b

:testCase value test1 test2 ... testn
    if "%~2"==""    exit /b 1
    if "%~1"=="%~2" exit /b 0
    shift /2 & goto %0

答案 1 :(得分:2)

首先,我认为谨慎地展示如何使用IF语句来完成它。批处理IF不支持OR逻辑。以下模拟OR:

@echo off
setlocal enableDelayedExpansion
set "mode=%~1"

set "aModes= TYPE1 TYPE2 "
set "bModes= TYPE1 TYPE3 "
set "cModes= TYPE3 "

if "!aModes:%mode%=!" neq "!aModes!" echo command A
if "!bModes:%mode%=!" neq "!bModes!" echo command B
if "!cModes:%mode%=!" neq "!cModes!" echo command C

现在可以替代IF

1)我能想到的一个半实用的东西是使用MODE作为标签,但我不喜欢它。不必要地使用CALL会明显变慢。您必须确保控制MODE值,否则您将收到难看的错误消息。此外,命令在代码中复制,因为相同的MODE运行多个命令。

@echo off
setlocal
set "mode=%~1"

call :%MODE%
:: remainder of logic
exit /b

:TYPE1
echo command A
echo command B
exit /b

:TYPE2
echo command A
exit /b

:TYPE3
echo command B
echo command C
exit /b

如果命令A和/或B和/或C是一个复杂的命令块,那么它们可以被制作成自己标记的子程序,并在适当的时候进行调用。这样可以防止复杂逻辑的复制。

2)另一种可能性是带有条件命令执行的FINDSTR,但这比IF慢,而且更尴尬。唯一的优点是它不需要额外的变量来实现OR逻辑。

@echo off
setlocal
set "mode=%~1"

echo %mode%|>nul findstr "TYPE1 TYPE2" && echo command A
echo %mode%|>nul findstr "TYPE1 TYPE3" && echo command B
echo %mode%|>nul findstr "TYPE3"       && echo command C

请注意,如果您的模式类似于BC和ABCD,则上述操作无效,因为BC包含在ABCD中。这可以通过引入一些括号来处理。

@echo off
setlocal
set "mode=%~1"

echo {%mode%}|>nul findstr "{TYPE1} {TYPE2}" && echo command A
echo {%mode%}|>nul findstr "{TYPE1} {TYPE3}" && echo command B
echo {%mode%}|>nul findstr "{TYPE3}"         && echo command C

最后,您可以使用MC ND的简单宏的想法,使上面看起来更优雅。

@echo off
setlocal
set "mode=%~1"

set "whenMode=echo {%mode%}|>nul findstr"

%whenMode% "{TYPE1} {TYPE2}" && echo command A
%whenMode% "{TYPE1} {TYPE3}" && echo command B
%whenMode% "{TYPE3}"         && echo command C

3)你可能会非常喜欢并使用batch macros with arguments的高级技术。这是good primer to the technology and development of batch macros with arguments

设置宏需要一些神秘的代码,但一旦定义,它就非常容易使用,并且非常快。最好的部分是它可以用于任何变量。在下面的示例中,我将它与MODE1和MODE2一起使用。

@echo off
setlocal disableDelayedExpansion
set "mode1=%~1"
set "mode2=%~2"

:: define LF as a Line Feed (newline) character
set ^"LF=^

^" Above empty line is required - do not remove

:: define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:: define a when macro that takes arguments
set when=%\n%
for %%# in (1 2) do if %%#==2 (setlocal enableDelayedExpansion^&for /f "tokens=1*" %%1 in ("!args!") do (%\n%
  set "test= %%~2 "%\n%
  for /f %%M in ("!%%1!") do (%\n%
    if "!test:%%M=!" neq "!test!" (%\n%
      endlocal%\n%
      endlocal%\n%
      (call )%\n%
    ) else (%\n%
      endlocal%\n%
      endlocal%\n%
      (call)%\n%
    )%\n%
  )%\n%
)) else setlocal^&set args=

:: ------- End of Initialization ---------------------

(%when% mode1 "TYPE1 TYPE2") && echo command A
(%when% mode1 "TYPE1 TYPE3") && echo command B
(%when% mode1 "TYPE3")       && echo command C

(%when% mode2 "TYPE1 TYPE2") && echo command X
(%when% mode2 "TYPE1 TYPE3") && echo command Y
(%when% mode2 "TYPE3")       && echo command Z

答案 2 :(得分:1)

我认为解决此问题的最清晰,最快的方法是通过array

@echo off
setlocal EnableDelayedExpansion

rem Define the array of equivalences from MODE values vs Command
set numCommands=0
for %%a in ("TYPE1|TYPE2=Command A"
            "TYPE1|TYPE3=Command B"
            "TYPE3=Command C") do (
   set /A numCommands+=1
   set "command[!numCommands!]=%%~a"
)

rem Get MODE as parameter:
set "MODE=%~1"

rem Execute the commands in order
for /L %%i in (1,1,%numCommands%) do (
   for /F "tokens=1,2 delims==" %%a in ("!command[%%i]!") do (
      set "options=|%%a|"
      if "!options:|%MODE%|=!" neq "!options!" ECHO Run: %%b
   )
)

编辑:或者以较短的方式,没有数组:

@echo off
setlocal EnableDelayedExpansion

set "MODE=%~1"

for %%i in ("TYPE1|TYPE2=Command A"
            "TYPE1|TYPE3=Command B"
            "TYPE3=Command C") do (
   for /F "tokens=1,2 delims==" %%a in (%%i) do (
      set "options=|%%a|"
      if "!options:|%MODE%|=!" neq "!options!" ECHO Run: %%b
   )
)