批处理文件似乎无缘无故地将变量设置为2

时间:2017-10-07 08:53:44

标签: windows batch-file

我正在制作一个简单的批处理脚本,以便在批处理脚本中找出数组。

代码:

@echo off
setlocal EnableDelayedExpansion
set inputCount=0
set outputCount=0

:input
cls
set /p !number%inputCount%!=Input %inputCount%: 
set /a inputCount=%inputCount%+1
if %inputCount% geq 3 goto output
goto input

:output
cls
echo !number%outputCount%!
set /a outputCount=%outputCount%+1
if %outputCount% geq 3 goto exit
goto output

:exit
pause
echo exit

在第4行,我将outputCount设置为0,然后我不会更改outputCount直到第16行我向其添加1

我希望第16行的输出为outputCount=0+1=1因此outputCount=1。但是,当我使用echo on运行代码以查看其正在执行的操作时,第16行的输出为outputCount=2+1=3,将outputCount设置为3

该计划似乎在第16行之前的某个时刻将outputCount设置为2而不是0,但我看不出原因。

1 个答案:

答案 0 :(得分:0)

首先,请查看Debugging a batch file,因为这是您编写批处理文件时需要学习的一课。

其次,阅读Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案,该答案为在命令提示符窗口set /?中运行的帮助输出提供了附加信息。

您似乎希望定义环境变量number0number1number2,并在用户输入中为其分配字符串。

用于提示用户输入字符串的命令是

set /P "variable=prompt text: "

set /P variable="prompt text: "

通常建议使用第一个变体,尽管批处理文件编码新手通常不会使用,因为在将字符串赋值给环境变量时不知道如何使用双引号。第二个变体特定于set /P也是可能的,并且在一些非常罕见的情况下确实需要,但在我看来应该避免使用,因为双引号在使用set时没有{被解释为不同{1}}。

因此,让我们通过使用/P四行注释来查看您的代码,在批处理文件的末尾添加一行rem并在命令提示符窗口中运行该批处理文件:

set

输出结尾只是rem @echo off setlocal EnableDelayedExpansion set inputCount=0 set outputCount=0 :input rem cls set /p !number%inputCount%!=Input %inputCount%: set /a inputCount=%inputCount%+1 if %inputCount% geq 3 goto output goto input :output rem cls echo !number%outputCount%! set /a outputCount=%outputCount%+1 if %outputCount% geq 3 goto exit goto output :exit rem pause echo exit set number 的一行。没有环境变量NUMBER_OF_PROCESSORS=2number0number1也会由number2输出。文件中的命令行set number会在echo !number%outputCount%!

的信息中生成三次

通过查看Windows命令解释器预处理每一行后真正执行的输出命令行,可以看到原因。

ECHO is OFF

用户输入的字符串,如果不是 RETURN ENTER 被提示用户点击,应该分配给的环境变量名称存储在环境变量 set /p !number%inputCount%!=Input %inputCount%: number0number1中。但是您的批处理文件永远不会定义环境变量number2number0number1,因为您的意图是将输入字符串存储到名为number2的变量中,{{ 1}}和number0。所以这个命令行终于执行了:

number1

由于语法错误,这些命令行会导致批处理退出,但由于在控制台窗口中可以看到延迟扩展的使用,因此不会出现这种情况。

解决方案是批处理代码,如下所示:

number2

此批处理文件的输出在第一个提示符set /p =Input 0: set /p =Input 1: set /p =Input 2: 上输入,第二个提示输入,第三个提示符@echo off setlocal EnableExtensions EnableDelayedExpansion set "Index=0" :Input cls set /A Index+=1 set /P "Number%Index%=Input %Index%: " if not %Index% == 3 goto Input cls set "Index=0" :Output set /A Index+=1 if defined Number%Index% echo Number%Index%=!Number%Index%! if not %Index% == 3 goto Output endlocal 为:

Hello!

好的,我们还没有输入一个数字,因为我们可以自由地输入任何东西,从Bye!输入错误的字符串。但批处理文件现在按预期工作。

进一步请注意Number1=Hello! Number3=Bye! 之后的字符串是算术表达式,它被解析为与命令行上的任何其他字符串完全不同。例如,可以通过仅使用变量名称来引用环境变量的当前值,而不包含百分号或感叹号。这样就可以在 IF FOR 命令块中使用算术表达式中的变量,而无需使用延迟扩展。在命令提示符窗口中运行Double quote " or | or < or > are bad inputs on user prompt时的帮助输出解释了这种不同的解析行为以及算术表达式中可以像set /A一样使用哪些运算符。

要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • set /?
  • +=
  • cls /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?

更多提示:

请勿在批处理文件中使用set /?,使用setlocal /?exit,请参阅Where does GOTO :EOF return to?

在验证用户输入任何内容并且输入的字符串实际上是一个数字(十进制,八进制或十六进制)之后,请确保根据您和用户的期望处理该数字。我的意思在于:

exit /B

您期望得到什么结果,goto :EOF或实际结果@echo off set "Number=020" set /A Number+=1 echo Result=%Number% pause

21开头的数字字符串被解释为八进制数。以170开头的数字字符串被解释为十六进制数字。将0x更改为0X,结果为020。为什么? 008对八进制数无效,因此被1替换为{1}}。