带有空字符串的子字符串扩展导致 If 子句中的错误

Sub-string expansion with empty string causes error in If clause

我有以下代码片段:

if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.

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

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

echo was unexpected at this time.

这是怎么回事?语法非常好,但为什么该命令行会失败?

即使是这里最有帮助的话题之一,How does the Windows Command Interpreter (CMD.EXE) parse scripts?,对于此类事情也没有提供对此行为的解释。

当我直接在命令提示符下执行相同操作时,一切正常。此外,当我尝试使用 delayed expansion 时也没有发生错误。

我的 companion answer to jeb's answer 到 "How does the Windows Command Interpreter (CMD.EXE) parse scripts?" 确实解释了这种行为。

我的 companion answer 提供了有关 % 扩展如何完全预测行为的必要详细信息。

如果你保持ECHO ON,那么你可以看到扩展的结果,错误信息是有道理的:

test.bat

@echo on
@set "ARGV="
if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.

--输出--

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

C:\test>if "~,1" echo  begins with a colon.


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

1)(Percent) Starting from left, scan each character for %. If found then

  • 1.1 (escape %) ... not relevant
  • 1.2 (expand argument) ... not relevant
  • 1.3 (expand variable)
    • Else if command extensions are disabled then ... not relevant
    • Else if command extensions are enabled then Look at next string of characters, breaking before % : or <LF>, and call them VAR (may be an empty list). If VAR breaks before : and the subsequent character is % then include : as the last character in VAR and break before %.
      • If next character is % then Replace %VAR% with value of VAR (replace with nothing if VAR not defined) and continue scan
      • Else if next character is : then
        • If VAR is undefined then Remove %VAR: and continue scan.
        • ... Remainder is not relevant

开始于

if "%ARGV:~,1%"==":" echo %ARGV% begins with a colon.

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

%ARGV:
%"==":
%ARGV%

你还剩下:

if "~,1" echo  begins with a colon.

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

一切都在命令行中工作,因为当变量未定义时,命令行变量扩展不会删除字符串。 (在 CmdLineParser:, Phase1(Percent) 底部附近的 jeb 回答中松散地解释了)