Подтвердить что ты не робот

Эквивалент оператора Switch в командном файле Windows

Интересно, существует ли простой способ ветвления выполнения в пакетном файле Windows в зависимости от значения одного выражения? Нечто похожее на переключение/регистр блоков в C, C++, С#, Java, JavaScript, PHP и других реальных языках программирования.

Мой единственный обходной путь - простой блок if/else, в котором одно и то же выражение многократно проверяется на равенство разных значений:

IF "%ID%"=="0" (
  REM do something
) ELSE IF "%ID%"=="1" (
  REM do something else
) ELSE IF "%ID%"=="2" (
  REM do another thing
) ELSE (
  REM default case...
)

Так глупо. Есть ли лучшее решение?

4b9b3361

Ответ 1

В итоге я использовал имена меток, содержащие значения для выражений падежа, как это было предложено AjV Jsy. В любом случае, я использую CALL вместо GOTO, чтобы перейти к правильному блоку регистра, и GOTO :EOF, чтобы вернуться назад. Следующий пример кода представляет собой полный пакетный скрипт, иллюстрирующий эту идею.

@ECHO OFF

SET /P COLOR="Choose a background color (type red, blue or black): "

2>NUL CALL :CASE_%COLOR% # jump to :CASE_red, :CASE_blue, etc.
IF ERRORLEVEL 1 CALL :DEFAULT_CASE # If label does not exist

ECHO Done.
EXIT /B

:CASE_red
  COLOR CF
  GOTO END_CASE
:CASE_blue
  COLOR 9F
  GOTO END_CASE
:CASE_black
  COLOR 0F
  GOTO END_CASE
:DEFAULT_CASE
  ECHO Unknown color "%COLOR%"
  GOTO END_CASE
:END_CASE
  VER > NUL # reset ERRORLEVEL
  GOTO :EOF # return from CALL

Ответ 2

Это проще читать:

IF "%ID%"=="0" REM do something
IF "%ID%"=="1" REM do something else
IF "%ID%"=="2" REM do another thing
IF %ID% GTR 2  REM default case...

Ответ 3

Компактная форма для коротких команд (без 'echo'):

IF "%ID%"=="0" ( ... & ... & ... ) ELSE ^
IF "%ID%"=="1" ( ... ) ELSE ^
IF "%ID%"=="2" ( ... ) ELSE ^
REM default case...

После ^ должен быть немедленный конец строки, без пробелов.

Ответ 4

Я обыскал switch / case в пакетных файлах сегодня и наткнулся на это. Я использовал это решение и расширил его с помощью goto exit.

IF "%1"=="red" echo "one selected" & goto exit
IF "%1"=="two" echo "two selected" & goto exit
...

echo "Options: [one | two | ...]

:exit 

При вводе состояния по умолчанию (эхо-строка) и дополнительных if, когда выбор найден.

Ответ 5

Я предполагаю, что все другие варианты были бы более загадочными. Для тех, кто любит читаемый и нешифрованный код:

IF        "%ID%"=="0" (
    REM do something

) ELSE IF "%ID%"=="1" (
    REM do something else

) ELSE IF "%ID%"=="2" (
    REM do another thing

) ELSE (
    REM default case...
)

Это как анекдот:

Маг: положи яйцо под шляпу, сделай магические пассы... Сними шляпу и... возьми то же яйцо, но на виде сбоку...

Решение IF ELSE не так уж и плохо. Это почти так же хорошо, как питон if elif else. Больше загадочных "яиц" можно найти здесь here.

Ответ 6

Может быть, немного поздно, но это делает:

set "case1=operation1"
set "case2=operation2"
set "case3=operation3"

setlocal EnableDelayedExpansion
!%switch%!
endlocal

% switch% заменяется перед выполнением строки. Серьезные недостатки:

  • Вы переопределяете переменные регистра
  • Нужно DelayedExpansion

Может в конечном итоге быть полезным в некоторых случаях.

Ответ 7

Попробуй таким образом. Чтобы выполнить некоторый список операций типа

  • Использовался корпус выключателя.
  • Проверка условных операторов.
  • Вызов функции с более чем двумя аргументами.

 @echo off
 :Start2 
    cls
    goto Start
    :Start
    echo --------------------------------------
    echo     Welcome to the Shortcut tool     
    echo --------------------------------------            
    echo Choose from the list given below:
    echo [1] 2017
    echo [2] 2018
    echo [3] Task

    set /a one=1
    set /a two=2
    set /a three=3
    set /a four=4
    set input=
    set /p input= Enter your choice:
    if %input% equ %one% goto Z if NOT goto Start2
    if %input% equ %two% goto X if NOT goto Start2
    if %input% equ %three% goto C if NOT goto Start2
    if %input% geq %four% goto N

    :Z
    cls
    echo You have selected year : 2017
    set year=2017
    echo %year%
    call:branches year

    pause
    exit

    :X
    cls
    echo You have selected year : 2018
    set year=2018
    echo %year%
    call:branches year
    pause
    exit

    :C  
    cls
    echo You have selected Task
    call:Task
    pause
    exit

    :N
    cls
    echo Invalid Selection! Try again
    pause
    goto :start2




    :branches
    cls
    echo Choose from the list of Branches given below:
    echo [1] January
    echo [2] Feburary
    echo [3] March
    SETLOCAL
    set /a "Number1=%~1"
    set input=
    set /p input= Enter your choice:
    set /a b=0
    set /a bd=3
    set /a bdd=4
    if %input% equ %b% goto N
    if %input% leq %bd% call:Z1 Number1,input if NOT goto Start2
    if %input% geq %bdd% goto N



    :Z1
    cls
    SETLOCAL
    set /a "Number1=%~1"
    echo year = %Number1%
    set /a "Number2=%~2"
    echo branch = %Number2%
    call:operation Number1,Number2
    pause
    GOTO :EOF


    :operation
    cls
    echo Choose from the list of Operation given below:
    echo [1] UB
    echo [3] B
    echo [4] C
    echo [5] l
    echo [6] R
    echo [7] JT
    echo [8] CT
    echo [9] JT
    SETLOCAL
    set /a "year=%~1"
    echo Your have selected year = %year%
    set /a "month=%~2"
    echo You have selected Branch = %month%
    set operation=
    set /p operation= Enter your choice:
    set /a b=0
    set /a bd=9
    set /a bdd=10
    if %input% equ %b% goto N
    if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
    if %input% geq %bdd% goto N




    :switch-case-N-1
    echo Januray
    echo %year%,%month%,%operation%
    goto :switch-case-end

    :switch-case-N-2
    echo Feburary
    echo %year%,%month%,%operation%
    goto :switch-case-end

    :switch-case-N-3
    echo march
    echo %year%,%month%,%operation%
    goto :switch-case-end

    :switch-case-end
       echo Task Completed
       pause
       exit
       goto :start2






    :Task
    cls
    echo Choose from the list of Operation given below:
    echo [1] UB
    echo [3] B
    echo [4] C
    echo [5] l
    echo [6] R
    echo [7] JT
    echo [8] CT
    echo [9] JT
    SETLOCAL
    set operation=
    set /p operation= Enter your choice:
    set /a b=0
    set /a bd=9
    set /a bdd=10
    if %input% equ %b% goto N
    if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
    if %input% geq %bdd% goto N




    :switch-case-N-1
    echo Januray
    echo %operation%
    goto :switch-case-end

    :switch-case-N-2
    echo Feburary
    echo %year%,%month%,%operation%
    goto :switch-case-end

    :switch-case-N-3
    echo march
    echo %year%,%month%,%operation%
    goto :switch-case-end

    :switch-case-end
       echo Task Completed
       pause
       exit
       goto :start2

Ответ 9

Харипрасад Дидупе предложил решение, предоставленное Batchography, но его можно немного улучшить. В отличие от других случаев, попадание в дело по умолчанию установит для ERRORLEVEL значение 1, а если это нежелательно, вам следует вручную установить для ERRORLEVEL значение 0:

goto :switch-case-N-%N% 2>nul || (
    rem Default case
    rem Manually set ERRORLEVEL to 0 
    type nul>nul
    echo Something else
)
...

Читаемость может быть улучшена за счет издержек call:

call:Switch SwitchLabel %N% || (
:SwitchLabel-1
    echo One
    goto:EOF     
:SwitchLabel-2
    echo Two
    goto:EOF
:SwitchLabel-3
    echo Three
    goto:EOF
:SwitchLabel-
    echo Default case
)

:Switch
goto:%1-%2 2>nul || (
    type nul>nul
    goto:%1-
)
exit /b

Несколько замечаний:

  1. Как указывалось ранее, это накладные расходы call;
  2. Требуется регистр по умолчанию. Если никаких действий не требуется, поместите rem внутрь избежать ошибки в скобках;
  3. Все случаи, кроме случая по умолчанию, выполняются в дополнительном контексте. Если вы хотите выйти из родительского контекста (обычно сценария), вы можете использовать this;
  4. Случай по умолчанию выполняется в родительском контексте, поэтому он не может быть в сочетании с другими делами (при достижении goto:EOF выйдет родитель контекст). Это можно обойти, заменив goto:%1- в подпрограмма с call:%1- по цене дополнительных накладных расходов call;
  5. Подпрограмма принимает префикс метки (без дефиса) и управляющую переменную. Без ярлыка переключатель префикса будет искать метки с префиксом :- (которые действительны) и не передача управляющей переменной приведет к регистру по умолчанию.