Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have the following code snippet:

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

As long as variable ARGV contains a non-empty value, or correctly said, it is defined, everything works as expected, hence if the string in ARGV begins with a colon, the echo command is executed.

However, as soon as I clear variable ARGV, a syntax error arises:

echo was unexpected at this time.

What is going on here? The syntax is perfectly fine, but why does that command line fail?

Even one of the most helpful threads here, How does the Windows Command Interpreter (CMD.EXE) parse scripts?, for such things does not deliver an explanation for this behaviour.

When I do the same directly in command prompt, everything is in order. Moreover, when I try it using delayed expansion no error occurs either.

like image 354
aschipfl Avatar asked Sep 07 '16 00:09

aschipfl


1 Answers

My companion answer to jeb's answer to "How does the Windows Command Interpreter (CMD.EXE) parse scripts?" does explain the behavior.

My companion answer gives the necessary details on how % expansion works to fully predict the behavior.

If you keep ECHO ON, then you can see the result of the expansion, and the error message makes sense:

test.bat

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

-- output --

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

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


The important rules from my answer that explain the expansion result are:

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

Starting with

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

The variable expansion expands all of the following strings to nothing because the variable is undefined:

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

And you are left with:

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

It works with delayed expansion because the IF statement is parsed before delayed expansion (explained in jeb's answer within phase 2)

Everything works from the command line because the command line variable expansion does not remove the string when the variable is not defined. (loosely explained in jeb's answer near the bottom within CmdLineParser:, Phase1(Percent))

like image 160
dbenham Avatar answered Nov 01 '22 07:11

dbenham