带有空字符串的子字符串扩展会导致If子句出错

asc*_*pfl 7 cmd batch-file syntax-error

我有以下代码片段:

if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.
Run Code Online (Sandbox Code Playgroud)

只要变量ARGV包含非空值,或者正确地说,它被定义,一切都按预期工作,因此如果字符串以ARGV冒号开头,echo则执行命令.

但是,只要我清除变量ARGV,就会出现语法错误:

echo was unexpected at this time.
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?语法完全正常,但为什么该命令行会失败?

即使是最有用的线程之一,Windows命令解释器(CMD.EXE)如何解析脚本?,因为这些事情没有提供这种行为的解释.

当我在命令提示符中直接执行相同操作时,一切都井然有序.此外,当我尝试使用延迟扩展时,也不会发生错误.

dbe*_*ham 5

我的同伴回答jeb回答 "Windows命令解释器(CMD.EXE)如何解析脚本?" 确实解释了这种行为.

我的同伴答案提供了有关%扩展如何工作以完全预测行为的必要细节.

如果您保持ECHO ON,那么您可以看到扩展的结果,并且错误消息是有意义的:

test.bat的

@echo on
@set "ARGV="
if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.
Run Code Online (Sandbox Code Playgroud)

- 输出 -

C:\test>test
echo was unexpected at this time.

C:\test>if "~,1" echo  begins with a colon.
Run Code Online (Sandbox Code Playgroud)


我的答案解释扩展结果的重要规则是:

1)(百分比)从左边开始,扫描每个字符%.如果发现那么

  • 1.1(逃避%) ...... 不相关
  • 1.2(扩展参数) ...... 不相关
  • 1.3(扩展变量)
    • 否则,如果禁用了命令扩展,则...... 不相关
    • 否则,如果启用了命令扩展,则查看下一个字符串,在之前% :或之前打破<LF>,并将其称为VAR(可能是一个空列表).如果VAR之前中断:,则后续字符%包含:在VAR中的最后一个字符并且之前中断%.
      • 如果是下一个字符,%则替换%VAR%为VAR的值(如果未定义VAR,则替换为空)并继续扫描
      • 否则,如果下一个字符是:那么
        • 如果未定义VAR,则删除%VAR:并继续扫描.
        • ... 剩余无关紧要

从...开始

if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.
Run Code Online (Sandbox Code Playgroud)

变量扩展将以下所有字符串扩展为空,因为变量未定义:

%ARGV:
%"==":
%ARGV%
Run Code Online (Sandbox Code Playgroud)

你剩下的就是:

if "~,1" echo  begins with a colon.
Run Code Online (Sandbox Code Playgroud)

它适用于延迟扩展,因为IF语句在延迟扩展之前被解析(在第2阶段的jeb答案中解释)

一切都在命令行中运行,因为命令行变量扩展在未定义变量时不会删除字符串.(在CmdLineParser中靠近底部的jeb答案中松散地解释:,Phase1(百分比))