2017-01-02 82 views
0

这是写这些批处理代码的行的正确方法,除了空格和不需要的百分号吗?为什么字符串比较提示用户输入的字符串/选项不能按预期工作?

:name 
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 below 
echo (6 char max) 
echo. 
set /p %player% = 

cls 
echo so you want your name to be %player% ? 
echo. 
echo 1) yes 
echo 2) no 

set /p %namechoice% = 
if %namechoice% == 1 goto check 
if %namechoice% == 2 goto name 


:check 
if /I %player% == %username% (goto gamestart) else goto suprise 

:suprise 

批量用户输入玩家名称后不输出。

checkname的字符串比较也不起作用。

命令行if %namechoice% == 1 goto check导致与错误消息批处理文件执行的断裂:

转到在这个时候意外的。

+1

丢失'='标志周围的空格。所以你的代码说'%namechoice% == 1'这永远不会是真的。在块使用'Goto:eof'后,下面的代码将不会运行。 – 2017-01-02 22:30:48

+3

不可以。仅在引用变量时才指定变量时不使用百分号。您还需要删除SET语句中等号之前的空格。'set/p namechoice ='另外,我的最佳做法是在我的比较周围使用引号,并且在等号之前或之后没有空格。'if'%namechoice%“==”1“goto check' – Squashman

+0

您也可以使用在你的':check'部分有一个'if' /'else'构造:'if“%player%”==“%username%”(goto gamestart)else goto suprise'(括号在这里是强制性的,因为没有它们,该语句不知道'else'之前的条件部分何时结束);使用这些字符串比较的引号可以避免在空字符串或特殊字符的情况下出现问题;另外,考虑使用'if/I“%player%”==“%username%”'做一个不区分大小写的比较,特别是因为你正在检查用户输入...看到这个:['if']( http://ss64.com/nt/if.html)... – aschipfl

回答

1

的主要错误是一个简单的语法问题:

环境变量只指定变量名没有百分号并用等号前面没有空格字符定义。

所以错的是

set /p %player% = 
set /p %namechoice% = 

,因为这两条线是真正执行命令SET

set /p = 
set /p = 

环境变量的情况下,前预处理阶段期间扩大playernamechoice不已经定义。有关如何定义环境变量权限的详细信息,请参见Why is no string output with 'echo %var%' after using 'set var = text' on command line?。它也解释了为什么空格字符在变量定义上留下等于符号变成变量名称的一部分,批处理文件编写器几乎总是不需要这些名称。

这种简单的语法问题可以在运行的批处理文件很容易地看到,而不@echo off在这一行修改,以@echo on的批处理文件或顶部或与来自::@echo off(无效标签)或rem @echo off(remark命令)注释在命令提示符窗口中输入具有完整路径的批处理文件的名称,而不是双击批处理文件。

有什么区别?

  1. @echo off随着命令线印刷到控制台窗口确实执行它们之前预处理(膨胀的环境变量)之后。这是批处理文件开发完成时的通缉行为。但在批处理文件的开发和测试过程中,显示​​Windows命令解释器真正执行的内容以查找编码错误绝对会​​更好。

  2. 在双击一个批处理文件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 

在顶部的评论解释了为什么环境变量Player与价值No name entered定义。批量用户可以自由选择RETURNENTER不输入任何内容或在输入名称之前误输入这两个密钥中的一个。在这种情况下,如果以前未定义,则环境变量Player或者仍未定义,或者如果之前已经定义,则其保持其当前值。如果用户什么都不输入,并且在这种情况下没有定义环境变量Player,这是不好的。因此玩家名称是用无效名称预定义的。

输入的玩家名称的长度也会过长。

而用户输入的字符串可能包含批量语法关键字符(如双引号,百分号,重定向操作符字符(尖括号,管道),&符号或延迟扩展启用感叹号。为防止在命令行执行前使用环境变量扩展输入的播放器名称导致语法错误导致的批处理退出,环境变量Player被引用到处,在批处理文件的顶部使用延迟扩展。

要打印一个空行,最好是使用echo/而不是echo.因为echo.可能会失败,是有点慢,因为Windows命令解释器搜索在DosTips论坛文章ECHO. FAILS to give text or blank line - Instead use ECHO/记录匹配模式echo.*的文件。

命令CHOICEset /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比命令SET的赋值运算符=处理不同。不要混合它们。

为了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • choice /?
  • cls /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • ping /?
  • rem /?
  • set /?
  • setlocal /?

而且也看到了的>nul解释微软的文章Using command redirection operators