Ced*_*ric 3 windows cmd if-statement batch-file
.bat 应该将用户输入与值进行比较。IF "%choice%"=="1"当我用 1 或 2 的输入测试它时,它不会进入。
这是批处理文件:
@echo off
rem ...
IF [%$ecbId%] == [] (
echo Enter '1' to blabla
echo Enter '2' to blabla
echo Enter anything to abort
set /p choice="Type input: "
IF "%choice%"=="1" (
echo toto1
rem save into property file
echo currentMaster=%ecb%>> MDC.properties
echo masterDcName=ECBDC>> MDC.properties
echo currentClone=%bdf%>> MDC.properties
echo cloneDcName=BDFDC>> MDC.properties
)
IF "%choice%"=="2" (
echo toto2
rem save into property file
echo currentMaster=%bdf%>> MDC.properties
echo masterDcName=BDFDC>> MDC.properties
echo currentClone=%ecb%>> MDC.properties
echo cloneDcName=ECBDC>> MDC.properties
)
IF NOT "%choice%"=="1" (
echo toto3
IF NOT "%choice%"=="2" (
echo toto4
echo Unknown input ... Aborting script
exit /b 400
)
)
)
Run Code Online (Sandbox Code Playgroud)
命令输出:
Enter '1' to blabla
Enter '2' to blabla
Enter anything to abort
Type input: 1
toto3
toto4
Unknown input ... Aborting script
Run Code Online (Sandbox Code Playgroud)
为什么它不进入IF "%choice%"=="1"条件?
这是一个工作批处理代码:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem ...
if "%$ecbId%" == "" (
echo Enter '1' to blabla
echo Enter '2' to blabla
echo Enter anything else to abort.
echo/
set "UserChoice=abort"
set /P "UserChoice=Type input: "
if "!UserChoice!" == "1" (
echo toto1
rem save into property file
>>MDC.properties echo currentMaster=%ecb%
>>MDC.properties echo masterDcName=ECBDC
>>MDC.properties echo currentClone=%bdf%
>>MDC.properties echo cloneDcName=BDFDC
)
if "!UserChoice!" == "2" (
echo toto2
rem save into property file
>>MDC.properties echo currentMaster=%bdf%
>>MDC.properties echo masterDcName=BDFDC
>>MDC.properties echo currentClone=%ecb%
>>MDC.propertiesecho cloneDcName=ECBDC
)
if not "!UserChoice!" == "1" (
echo toto3
if not "!UserChoice!" == "2" (
echo toto4
echo Unknown input ... Aborting script
endlocal
exit /B 400
)
)
)
endlocal
Run Code Online (Sandbox Code Playgroud)
使用命令在批处理文件的顶部启用延迟扩展setlocal EnableExtensions EnableDelayedExpansion。命令SETLOCAL不仅启用延迟扩展,还将整个命令进程环境保存在堆栈中,如我在更改目录命令 cd ..not working in batch file after npm install 的回答中详细解释的那样。命令进程环境在执行命令ENDLOCAL 时从堆栈中恢复,这也将由 Windows 命令处理器在未明确执行时退出批处理文件处理时完成endlocal。
开始与在命令块设置或修改的所有环境变量(,并与匹配的结束)和相同命令块中还引用必须使用延迟扩展被引用。
当 Windows 命令处理器到达第四行时,直到最后一行的整个命令块都被解析和预处理,然后再评估IF条件。在这个预处理步骤中,从第 4 行到第 36 行的整个块中扩展了所有用百分号引用的环境变量。
这意味着所有出现的%ecb%和%bdf%都被环境变量的当前值替换,ecb并且bdf在第4 行上的IF条件完全像%$ecbId%在IF条件本身中一样被评估之前。
只是UserChoice在解析/预处理整个块时不会扩展环境变量,因为此环境变量是使用延迟扩展引用的。
因此,可以为abort环境变量分配一个默认值,例如UserChoice在批处理用户点击的情况下只输入RETURN或ENTER不输入任何内容。
由于对环境变量使用延迟扩展,用户输入的字符串永远不会在解析/预处理阶段扩展UserChoice。的当前字符串值UserChoice始终在评估每个IF条件时进行解释。
Windows 命令处理器的这种行为可以很容易地观察到
@echo off从批处理文件的第一行中删除,Windows 命令处理器现在总是在解析后输出行或命令块,然后才真正执行。因此可以看出,在达到第一个IF条件时,%...%如果参考环境变量尚未定义,则整个命令块已经被预处理,并分别用环境变量中的适当字符串替换了所有出现的。并且可以看出,当整个命令块中的下一个命令行由 Windows 命令解释器执行时,%ecb%和的值%bdf%永远不会再次修改。
更紧凑的是:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem ...
if "%$ecbId%" == "" (
echo Enter '1' to blabla
echo Enter '2' to blabla
echo Enter anything else to abort.
echo/
set "UserChoice=abort"
set /P "UserChoice=Type input: "
if "!UserChoice!" == "1" (
echo toto1
rem save into property file
>>MDC.properties echo currentMaster=%ecb%
>>MDC.properties echo masterDcName=ECBDC
>>MDC.properties echo currentClone=%bdf%
>>MDC.properties echo cloneDcName=BDFDC
) else if "!UserChoice!" == "2" (
echo toto2
rem save into property file
>>MDC.properties echo currentMaster=%bdf%
>>MDC.properties echo masterDcName=BDFDC
>>MDC.properties echo currentClone=%ecb%
>>MDC.properties echo cloneDcName=ECBDC
) else (
echo Unknown input ... Aborting script
endlocal
exit /B 400
)
)
endlocal
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是使用choice自 Windows Vista 以来默认可用的命令。它的优点是用户只需要按三个键之一。在这种情况下不需要延迟的环境变量扩展,因为choice退出时的值取决于分配给环境变量的按键,errorlevel即使在命令块内也可以在没有延迟扩展的情况下进行评估。
@echo off
rem ...
if "%$ecbId%" == "" (
echo Enter '1' to blabla
echo Enter '2' to blabla
echo Enter 'A' to abort.
echo/
%SystemRoot%\System32\choice.exe /C 12A /N /M "Type input:"
if errorlevel 3 (
echo Aborting script
exit /B 400
) else if errorlevel 2 (
echo toto2
rem save into property file
>>MDC.properties echo currentMaster=%bdf%
>>MDC.properties echo masterDcName=BDFDC
>>MDC.properties echo currentClone=%ecb%
>>MDC.properties echo cloneDcName=ECBDC
) else (
echo toto1
rem save into property file
>>MDC.properties echo currentMaster=%ecb%
>>MDC.properties echo masterDcName=ECBDC
>>MDC.properties echo currentClone=%bdf%
>>MDC.properties echo cloneDcName=BDFDC
)
)
Run Code Online (Sandbox Code Playgroud)
由于字符被指定为选项后的第一个字符,用户必须按1导致choice以值退出,或让以值退出的键或键(不区分大小写)导致以值退出,因为字符被指定为第三个字符在 option 之后的下一个参数字符串中。额外确认后,可以额外按下退出批处理文件处理。所有其他按键都被忽略并导致输出铃声,通知用户按下了错误的键。11/C2choice2Achoice3A/CCtrl+Cchoice
现在最好choice只使用文件名或完全限定的文件名对此类用户提示使用该命令,以获得最大的执行安全性。