批处理文件"如果"陈述错误

时间:2015-11-30 02:35:40

标签: windows batch-file if-statement cmd

我似乎在制作这个节目时遇到了很多麻烦。 我最后只有一个错误。这是我的代码:

[DataMember]

无论如何,如果你能向我解释什么是错的。

2 个答案:

答案 0 :(得分:1)

你的代码实际上完全按照你所说的去做,它只是走得太快你无法注意到它。

当您检查变量是否存在时,请不要将其包含在%!中。 if not defined varname基本上说,“如果没有名为'varname'的变量,那么就这样做......”;当您使用%!包围它时,可以用其值替换变量。如果我在提示符处输入10,则代码将显示“如果没有名为10的变量,则清除屏幕并返回到tutq。”由于 没有名为10的变量,因此您将陷入无限循环。

If not defined !tutnum! (更改为If not defined tutnum (,您的代码就可以使用。

答案 1 :(得分:0)

你已经接受了一个很好的答案 - 请保持原样。这是补充信息,如果不是你那么可能对那些面临同样问题的人有用。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "letequ=a(1 b(2 c(3 d(4 e(5"
:tutq
cls
FOR %%a IN (%letequ%) DO echo %%a
SET "tutnum="
SET /p "tutnum=What is the first letter of your name? "
IF NOT DEFINED tutnum GOTO tutq
FOR %%a IN (%letequ%) DO (
 SET letterandnumber=%%a
 SET "letter=!letterandnumber:~0,1!"
 SET "number=!letterandnumber:~2!"
 IF "!number!"=="%tutnum%" (
  ECHO The first letter of your name is "!letter!"&pause&GOTO :EOF)
)
GOTO tutq

所以 - 我没有费心完成字母/数字集。如何做到这一点应该是相当明显的。

请注意设置字符串值的方法。该语法确保一行上的尾随空格包含在分配的值中,这有时会导致问题。例如,

SET tutnum=

应该从环境中清除tutnum,这意味着就cmd而言,它的值为 nothing 但是,如果在行尾有杂散(且不方便)的空格,它将设置为那些空格,if defined tutnum为真

SET "tutnum="

会根据需要清除tutnum,杂散空格或不。

set /p之前设置变量似乎是多余的,但如果对set /p的响应只是 Enter ,那么变量将保持不变 - 它不会自动没有可能的值。此技术可用于指定默认值

set "var=default"
set /p "var=prompt-string"
如果用户回复 Enter

会将default分配给var

这可以像

一样使用
set "var=default"
set /p "var=prompt-string [%var%]"

向用户显示用户响应时将使用的值 Enter

要检查的下一个项目是for循环。 for可以受到各种jiggery-pokery的影响,但基本的是

for %%x in (list of items separated by spaces) do something

其中列表中的每个项目依次分配到%%a,因此列表leteq中的每个项目依次分配给%%a%%a采用值“a(1”“b(2”“c(3”“d(4”和“e(5”,然后 具有该值。

对于代码的 analyze-the-entry 部分,某些

 SET letterandnumber=%%a
 SET "letter=!letterandnumber:~0,1!"
 SET "number=!letterandnumber:~2!"
 IF "!number!"=="%tutnum%" (
  ECHO The first letter of your name is "!letter!"&pause&GOTO :EOF)

这里的对象是 substring %%a例子中的值:“c(3”。我们不能做%%a的直接子串,所以我们分配%%a的值为letterandnumber,而子串

子串语法是

%var:~m,n%
  • 如果m>> = 0,那么子字符串的开头是var的第m个字符,从“字符0”开始
  • 如果m <0,那么子字符串的开头是var
  • end 中的第m个字符
  • 如果n> 0,则n是子字符串的长度
  • 如果n <0,那么子字符串的结尾是var结尾中的第n个字符
  • n可以省略。如果省略,子字符串是“从起始位置到结尾”
  • 对于%模式,
  • !可能为delayedexpansion

因此letter设置为~0,1,即letterandnumber长度为1的第一个字符,同样number设置为~2 - 第三个字母直到字符串的结尾。

由于letterandnumber在循环中(或在任何带括号的语句序列中,也称为“块”)中设置,因此它可能显示为两个单独的值。 %letterandnumber%指的是第一次遇到和解析块时的值 ,而!letterandnumber!在运行时引用值,因为它可能在运行时设置块!var!语法仅在先前已执行setlocal enabledelayedexpansion命令时有效。

原因是cmd%var%的当前值替换任何var,然后检查语句的有效性。在块执行之前,!var!不会被替换。

这个序列的结果是显着的,如果不理解会导致一些剧烈的头痛。

假设我们有(请注意使用密闭括号,而不是打开)

SET "letequ=a)1 b)2 c)3"
FOR %%a IN (%letequ%) DO echo %%a

这将导致语法错误,因为 cmd将首先用其当前值替换leteq,然后然后解析它,所以它看到了

FOR %%a IN (a)1 b)2 c)3) DO echo %%a

假设第一个闭括号结束列表并期望do但找到1以便报告问题。

解决此问题的一种方法是转义错误解释的,方法是在其前面加上一个插入符 ^

SET "letequ=a^)1 b^)2 c^)3"
FOR %%a IN (%letequ%) DO echo %%a

cmd现在看到FOR %%a IN (a^)1 b^)2 c^)3) DO echo %%a并认识到^)表示“此括号是数据,而不是命令的一部分”因此它对语法感到满意并继续执行代码。< / p>

另一种方式是(如果delayedexpansion有效)

SET "letequ=a)1 b)2 c)3"
FOR %%a IN (!letequ!) DO echo %%a
命令通过有效性检查之后,

cmd才会替换该值,因此不会出现错误。