我是批处理新手,因此我无法弄清楚,为什么会出现语法错误??
这是我的代码:
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
)
Run Code Online (Sandbox Code Playgroud)
这只是一个“为了好玩”的项目,但我想知道为什么我会收到这个烦人的错误!
首先,阅读有关在命令行上使用“set var = text”后为什么没有带有“echo %var%”的字符串输出的答案?它解释了如何将正确的字符串值分配给环境变量。错误的是set variable = value将SPACE值分配给具有名称变量的环境变量SPACE,因此在此命令行之后没有具有名称变量的环境变量。
在大多数情况下完全错误也是set %variable%=value因为此命令行将值分配给环境变量的名称由环境变量变量的值定义的名称。
其次,在使用命令块的命令完全执行之前,所有环境变量引用%variable%在命令块内(以匹配开始和结束的语法完成的所有环境变量引用都被环境变量)的当前值扩展。这意味着所有%variable%都被引用的环境变量的当前值替换,如果名称为variable 的变量尚未定义,则该值没有任何意义。
让我们看看cmd.exe命令块真正执行的是什么,例如:
set "hostname02="
set "hostname1=0"
IF %hostname1% == 0 (
SET %hostname02% = 1
echo %hostname02% >> a.txt
PAUSE
)
Run Code Online (Sandbox Code Playgroud)
真正执行的命令行是:
set "hostname02="
set "hostname1=0"
IF 0 == 0 (
SET = 1
echo 1>>a.txt
PAUSE
)
Run Code Online (Sandbox Code Playgroud)
结果是通过cmd.exe错误消息退出执行批处理文件:
语法错误。
这可以通过在命令提示符窗口中不使用@echo off或使用运行批处理文件而@echo ON不是双击批处理文件来查看。另请参阅调试批处理文件。
批处理文件程序员必须始终考虑在处理批处理脚本中的行之后命令行是如何真正执行的,而不是它们是如何写入批处理文件的,尤其是在%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
Run Code Online (Sandbox Code Playgroud)
此批处理文件首先设置本地环境,并根据此处的要求启用命令扩展,并禁用延迟环境变量扩展,因为下面的代码不需要。EnableExtensions DisableDelayedExpansion命令使用的参数setlocal可以省略,因为命令扩展默认启用,延迟扩展在启动新命令进程时默认禁用,如双击批处理文件所做的那样。但始终建议明确定义批处理文件所需的环境。有关命令SETLOCAL和ENDLOCAL 的详细信息,请阅读此答案。
如果当前目录中根本存在此文件,则下一行将文件的第一行分配a.txt给环境变量hostname1,当然这可能与批处理文件的目录不同,具体取决于批处理文件是如何启动以执行的cmd.exe。
带有选项的FOR命令/F通常用于逐行读取文本文件,并将从文件中读取的字符串分配给环境变量。但set /P variable=<file.txt也可用于将第一行分配file.xt给环境变量variable。
第四个命令行验证是否hostname1现在定义了变量,如果a.txt当前目录中不存在文件或此文件以空行开头,则情况并非如此。如果在第三行之后没有定义环境变量,hostname1则使用 value0定义。
接下来hostname1输出变量的当前值用于视觉验证。
然后使用三个IF条件来运行区分大小写的字符串比较。要比较的字符串用双引号括起来,这使得批处理文件更安全,不会因为语法错误而退出执行,这取决于从文件中读取的字符串a.txt。但是这个解决方案仍然不是 100% 的故障安全,请参阅如何停止 Windows 命令解释器在不正确的用户输入上退出批处理文件执行的答案?有关如何在使用set /P用户输入的字符串值或从每个用户可以在运行批处理文件之前编辑的文件中读取的字符串值时如何获取批处理文件代码的详细信息。
分配给hostname02和的字符串值hostname03在代码中是固定的,因此这些字符串值也可以直接写入文件,a.txt而无需引用环境变量hostname02并hostname03在需要延迟环境变量扩展的命令块中定义。
重定向操作符>>和文件名写在一行的开头,只要批处理文件中的两个命令行上没有尾随空格,就可以真正写入文件a.txt,1无论2是否有尾随空格echo。对使用echo 1 >>a.txt之间的空间1,并>>会也被写入文件a.txt。并且echo 1>>a.txt根本不会写入1file a.txt。有关详细信息,请阅读有关使用命令重定向运算符的 Microsoft 文章。Windows命令处理器重新格式化>>a.txt echo 1来echo 1 1>>a.txt此命令行执行之前。所以>>a.txt在为了更好的可读性的缩进空格之后的行首被移动Windows 命令解释器在解析到命令行末尾时插入一个 1(空格和一个)左重定向运算符>>。
VBScript 可以使用cscript.exe– Windows 脚本主机的控制台版本 – 或wscript.exe– Windows 脚本主机的GUI版本执行。命令CALL不是执行 VBScript 的正确命令。因此批处理文件用于wscript.exe运行仅显示一个简单消息框的 VBScript。
要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
del /?echo /?endlocal /?goto /?if /?pause /?set /?setlocal /?wscript /?| 归档时间: |
|
| 查看次数: |
12401 次 |
| 最近记录: |