带有空字符串的子字符串扩展导致 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 回答中松散地解释了)
我有以下代码片段:
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 回答中松散地解释了)