主要错误是一个简单的语法问题:
环境变量的定义只需指定变量名称,不带百分号,且等号前不带空格字符。
所以错误的是
set /p %player% =
set /p %namechoice% =
因为这两行在真正执行命令之前的预处理阶段被扩展SET to
set /p =
set /p =
如果有环境变量player
and namechoice
尚未定义。看为什么在命令行上使用“set var = text”后没有带有“echo %var%”的字符串输出?有关如何定义环境变量的详细信息,请参阅权利。它还解释了为什么变量定义上等号左边的空格字符成为变量名称的一部分,而批处理文件编写器几乎总是不需要它。
在运行批处理文件时可以很容易地看到这种简单的语法问题without @echo off
在批处理文件的顶部或将此行修改为@echo on
或注释掉::@echo off
(无效标签)或rem @echo off
(注释命令)从命令提示符窗口中输入批处理文件的名称(带双引号的完整路径),而不是双击批处理文件。
有何不同?
With @echo off
命令行是not在真正执行它们之前进行预处理(扩展环境变量)后打印到控制台窗口。这是批处理文件开发完成后所需的行为。但在批处理文件的开发和测试过程中,最好显示 Windows 命令解释器实际执行的内容,以发现编码错误。
双击批处理文件时cmd.exe
开始使用选项执行批处理文件/C
用于在批处理文件执行终止时自动关闭控制台窗口,无论执行成功还是错误。这使得无法看到 Windows 命令解释器输出的语法错误等导致立即退出批处理文件执行的情况。因此,建议在批处理文件开发期间从手动打开的命令提示符窗口中运行它,如此例所示cmd.exe
以选项开始/K
即使批处理完成后也保持控制台窗口打开,除非批处理文件使用命令exit
不带参数/B
。这使得还可以查看导致批处理意外退出的错误的错误消息。
稍后,当批处理文件按预期工作时,第一行可以是@echo off
再次,当然可以通过双击来启动批处理文件。但在批处理文件开发过程中,最好始终在命令提示符窗口中运行批处理文件。向上/向下箭头键可用于滚动输入的字符串列表,这使得还可以轻松地重新输入例如玩家姓名。
以下是重写的批处理代码,其中包含一些改进和注释:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Define a too long player name before prompting the user for the player
rem name. This too long player name is kept in case of user hits just the
rem key RETURN or ENTER without entering anything at all. Then test for
rem entered name has not more than 6 characters. Delayed expansion is used
rem as the user could enter characters like " ! % ... which would in further
rem batch code execution result in exiting batch processing because of syntax
rem error or in unexpected behavior on referencing player name with expansion
rem before running the command.
:PromptForName
cls
echo Now that we've got your color figured out, what about your name?
echo Simply type the name you want for your character into the space
echo below (6 char max).
echo/
set "Player=No name entered"
set /P "Player=Player name: "
if not "!Player:~6!" == "" goto PromptForName
echo/
echo/
echo 1) yes
echo 2) no
echo/
choice /C:12 /N "So you want your name to be !player!? "
if errorlevel 2 goto PromptForName
if /I "!player!" == "%USERNAME%" goto GameStart
echo Surprise
endlocal
goto :EOF
:GameStart
echo/
echo Okay !Player!, let's play^^!
rem Wait 3 seconds using PING instead of TIMEOUT before exiting the
rem batch file because the command TIMEOUT does not exist on Windows XP.
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 4 >nul
endlocal
The comment at top explains why the environment variable Player
is defined with value No name entered
. The batch user has the freedom to hit just RETURN or ENTER without entering anything at all or hits by mistake one of those 2 keys before entering a name. In this case the environment variable Player
is either still not defined if not defined before, or it keeps its current value if already defined before. It is not good if the user enters nothing and the environment variable Player
is not defined in this case. Therefore the player name is predefined with an invalid name.
输入的玩家姓名的长度也经过测试是否太长。
用户输入的字符串可能包含批处理语法关键字符,例如双引号、百分号、重定向运算符字符(尖括号、管道)、与号或启用延迟扩展的感叹号。为了防止在命令行执行之前使用环境变量扩展时输入的玩家名称出现语法错误而导致批处理退出,环境变量Player
随处引用,并在批处理文件顶部启用延迟扩展。
要打印空行,最好使用echo/
代替echo.
因为echo.
可能会失败并且速度会慢一点,因为 Windows 命令解释器会搜索与模式匹配的文件echo.*
如 DosTips 论坛文章中所述回声。无法给出文本或空行 - 而是使用 ECHO/.
命令CHOICE比set /P VariableName=Prompt text
如果用户必须输入特定的键。命令CHOICE不允许用户输入批处理文件编写器不需要的内容,因此对于选择菜单来说更安全。
当前用户的帐户名引用%USERNAME%
还可以包含空格字符。因此,强烈建议将包含的整个字符串括起来%USERNAME%
始终用双引号引起来。
"%USERNAME%"
字符串比较的右侧要求左侧的字符串也用双引号括起来,因为命令IF比较两个字符串并包含双引号。
由于这个原因,条件
if /I !player! == "%USERNAME%"
仅当批处理文件用户输入带双引号的玩家名称时才为真,这是不太可能的。左侧也必须使用双引号。
用双引号括起来或不用双引号括起来的两个比较字符串周围的空格字符数并不重要。
在命令提示符窗口中执行以下批处理文件
@echo on
@setlocal EnableExtensions EnableDelayedExpansion
@set "Player=<|>"
if /I "!Player!"=="%SystemRoot%" echo Strings are equal.
if /I "!Player!" == "%WinDir%" echo Strings are equal.
if /I "!Player!" == "%Player%" echo Strings are equal.
if /I "!Player!"== "!Player!" echo Strings are equal.
if /I !Player! == !Player! echo Strings are equal.
@endlocal
结果输出
if /I "!Player!" == "C:\WINDOWS" echo Strings are equal.
if /I "!Player!" == "C:\WINDOWS" echo Strings are equal.
if /I "!Player!" == "<|>" echo Strings are equal.
Strings are equal.
if /I "!Player!" == "!Player!" echo Strings are equal.
Strings are equal.
if /I !Player! == !Player! echo Strings are equal.
Strings are equal.
可以看到比较运算符周围有空格字符==
与命令的执行无关IF。 Windows 命令处理器在执行之前对命令行进行漂亮的格式化IF命令。
但是要比较的字符串中的空格字符需要使用双引号,否则很可能会由于批处理文件执行时出现语法错误而导致批处理退出。
Note:等于运算符==
命令的IF与赋值运算符的处理方式不同=
命令的SET。不要混合它们。
为了了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
choice /?
cls /?
echo /?
endlocal /?
goto /?
if /?
ping /?
rem /?
set /?
setlocal /?
另请参阅 Microsoft 文章使用命令重定向运算符的解释>nul
.