命令的语法不正确吗?

时间:2018-12-03 10:43:28

标签: batch-file

我是新手,因此我不知道为什么会出现语法错误?

这是我的代码:

set /p hostname1=<a.txt


echo %hostname1%

PAUSE

IF %hostname1% == 0 (
    SET %hostname02% = 1
    echo %hostname02% >> a.txt
    PAUSE

) 

IF %hostname1% == 1 (

    SET %hostname03% = 2
    echo %hostname03% >> a.txt
    PAUSE
    exit
) 

IF %hostname1% == 2 (
    echo MSGBOX "Message" > %temp%\TEMPmessage.vbs
    call %temp%\TEMPmessage.vbs
    del %temp%\TEMPmessage.vbs /f /q
) 

这只是一个“有趣”的项目,但我想了解为什么会收到这个令人讨厌的错误!

2 个答案:

答案 0 :(得分:2)

首先,请阅读Why is no string output with 'echo %var%' after using 'set var = text' on command line?的答案,它说明了如何为环境变量分配正确的字符串值。错误的set variable = value SPACE 分配给名称为 variable SPACE 的环境变量,为此原因是在此命令行之后没有名称为 variable 的环境变量。

在大多数情况下,set %variable%=value也是完全错误的,因为此命令行将 value 分配给环境变量,该变量的名称由环境变量的 value 定义变量


第二,在命令块中,以%variable%开头并以匹配的(结尾的命令块中以语法)完成的所有环境变量引用均在使用该命令之前被环境变量的当前值扩展命令块完全执行。这意味着所有%variable%被引用的环境变量的当前值替换,如果尚未完全定义名称为 variable 的变量,则为空。

让我们看一下cmd.exe对于以下命令块实际执行的操作:

set "hostname02="
set "hostname1=0"

IF %hostname1% == 0 (
    SET %hostname02% = 1
    echo %hostname02% >> a.txt
    PAUSE
)

真正执行的命令行是:

set "hostname02="
set "hostname1=0"
IF 0 == 0 (
SET  = 1
 echo   1>>a.txt
 PAUSE
)

结果是cmd.exe退出批处理文件,并显示错误消息:

  

语法错误。

这可以通过在命令提示符窗口中运行不带@echo off或不带@echo ON的批处理文件而不是双击批处理文件来看到。另请参见debugging a batch file

批处理文件程序员必须始终考虑在批处理脚本中处理命令行后 的实际执行方式,而不是考虑如何在批处理文件中编写命令行,尤其是在{{ 1}}会在脚本执行期间动态修改代码。


有问题的示例代码的有效代码是:

%variable%

此批处理文件首先根据需要在此处设置具有启用的命令扩展名的本地环境,并根据以下代码的需要禁用延迟的环境变量扩展。可以省略有关使用命令@echo off setlocal EnableExtensions DisableDelayedExpansion if exist a.txt set /P hostname1=<a.txt if not defined hostname1 set "hostname1=0" echo hostname1 is: %hostname1% if "%hostname1%" == "0" ( set hostname02=1 >>a.txt echo 1 ) else if "%hostname1%" == "1" ( set hostname03=2 >>a.txt echo 2 goto EndBatch ) else if "%hostname1%" == "2" ( echo MSGBOX "Message">"%TEMP%\TEMPmessage.vbs" %SystemRoot%\System32\wscript.exe "%TEMP%\TEMPmessage.vbs" del "%TEMP%\TEMPmessage.vbs" ) :EndBatch endlocal pause 的参数EnableExtensions DisableDelayedExpansion,因为默认情况下启用了命令扩展名,并且在启动新命令过程时默认禁用了延迟扩展,就像双击批处理文件一样。但是,始终建议明确定义批处理文件所需的环境。阅读this answer,了解有关命令 SETLOCAL ENDLOCAL 的详细信息。

如果该文件位于当前目录中,则下一行将文件setlocal的第一行分配给环境变量a.txt,这当然可能与批处理文件的目录不同,这取决于批处理的方式文件已由hostname1开始执行。

带有选项cmd.exe的命令 FOR 通常用于逐行读取文本文件,并将从文件中读取的字符串分配给环境变量。但是/F也可以仅用于将set /P variable=<file.txt的第一行分配给环境变量file.xt

第四个命令行验证是否现在定义了变量variable,如果当前目录中不存在文件hostname1或此文件以空行开头,则不是这样。如果未在第三行之后定义环境变量a.txt,则其值应为hostname1

接下来,输出变量0的当前值以进行视觉验证。

然后使用三个 IF 条件运行区分大小写的字符串比较。要比较的字符串用双引号引起来,这使得批处理文件在执行退出时更加安全,因为语法错误取决于从文件hostname1读取的字符串。但是,此解决方案仍然不是100%故障安全的,有关如何通过用户输入或从字符串中读取字符串值来使用a.txt来获取批处理文件代码故障安全的详细信息,请参见How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?的答案每个文件,在运行批处理文件之前,每个用户都可以编辑该文件。

分配给set /Phostname02的字符串值在代码中是固定的,因此这些字符串值也可以直接写到文件hostname03中,而无需引用环境变量{{ 1}}和a.txt在命令块中定义,这将需要延迟环境变量扩展。

重定向操作符hostname02和文件名写在一行的开头,仅将hostname03>>真正写到文件a.txt中,而没有尾随空格因为批处理文件中的两个1命令行上没有尾随空格。使用2时,echoecho 1 >>a.txt之间的空格也将写入文件1中。 >>根本不会将a.txt写入文件echo 1>>a.txt。有关详细信息,请阅读有关Using command redirection operators的Microsoft文章。 Windows命令处理器在执行此命令行之前将1格式化为a.txt。因此,>>a.txt echo 1在缩进空格后的行首,以提高可读性,Windows command interpreter on parsing通过向重定向操作符{插入一个echo 1 1>>a.txt(空格和一个)而移至命令行的末尾{1}}。

使用>>a.txt – Windows脚本宿主的控制台版本–或使用 1GUI版本的Windows脚本宿主执行VBScript。命令 CALL 不是执行VBScript的正确命令。因此,批处理文件使用>>运行只显示一个简单消息框的VBScript。

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

  • cscript.exe
  • wscript.exe
  • wscript.exe
  • del /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • pause /?

答案 1 :(得分:0)

set /p hostname1=<a.txt


echo %hostname1%

PAUSE

:: this will check if the string hostname1 is "0"
IF "%hostname1%" == "0" (
    SET "hostname02=1"
    echo !hostname02! >> a.txt
    PAUSE

) 

IF %hostname1% == 1 (

    SET "hostname03=2"
    echo !hostname03! >> a.txt
    PAUSE
    exit
) 

IF %hostname1% == 2 (
    echo MSGBOX "Message" > %temp%\TEMPmessage.vbs
    call %temp%\TEMPmessage.vbs
    del %temp%\TEMPmessage.vbs /f /q
)

尝试这样。