3

I am trying to use the Windows CMD SET string manipulation versions in a programmatic way. The two versions of SET are ...

SET New_String=%String:Old_Text=New_Text%

In variable String replace Old_Text with New_Text, and return result in variable New_String.

SET New_String=%String:~Number_Of_Chars_To_Skip,Number_Of_Chars_To_Keep%

In variable String extract Number_Of_Chars_To_Keep after skipping Number_Of_Chars_To_Skip, and return result in variable New_String

Old_Text, New_Text, Number_Of_Chars_To_Skip, Number_Of_Chars_To_Keep must all be literals, not variables. So, typical usage would be like this ...

SET New_String=%String:abcd=fghi%
SET New_String=%String:~2,4%

Usage like this won't work ...

SET New_String=%String:%Old_Text%=%New_Text%%
SET New_String=%String:~%Skip_Count%,%Keep_Count%%

To do the above two SETs you have to CALL SET, like ...

CALL SET New_String=%%String:%Old_Text%=%New_Text%%%
CALL SET New_String=%%String:~%Skip_Count%,%Keep_Count%%%

So, I have this following test code fragment ...

SET "Chars=" & SET "String=0123456789" & SET "Skip=1" & SET "Keep=3"
CALL SET Chars=%%String:~%Skip%,%Keep%%%
ECHO Chars="%Chars%" (expected to be "123")

From a CMD file this works correctly. The CALL has been expanded to SET Chars=%string:~1,3% and has returned the expected result 123. But, and a big but it is, from a CMD Window (with the same variables) the exact same CALL SET returns this ...

%0123456789Skip%,3%%

Why doesn't this work in a CMD Window? I researched around and haven't found any info explaining why.

TheBrenny
  • 528
  • 3
  • 19
Larry8811
  • 189
  • 1
  • 4

1 Answers1

1

According to the thread How does the Windows Command Interpreter (CMD.EXE) parse scripts?, batch files and command lines are parsed differently, particularly when it comes to environment variable expansion.

The batch file parser replaces two consecutive percent signs by one literal one, while the command line parser does not. Hence CALL SET Chars=%%String:~%Skip%,%Keep%%% works within a batch file but not in cmd.

To achieve the same resut in cmd, you could use this:

CALL SET Chars=%^String:~%Skip%,%Keep%%

Actually, this does nothing but specifying a variable named ^String, which is expected to be not defined. In contrast to the batch file parser, the command line parser does not replace an undefined variable by an empty string, so ^String is kept literally. Regard that the ^ is handled after % variable expansion. Variables %Skip% and %Keep% are expanded as expected, so the resulting expression is SET Chars=%String:~1,3%.

To prove that, simply do SET String=something, so the result is going to be ome.


Note that the quoted SET syntax CALL SET "Chars=%^String:~%Skip%,%Keep%%" fails, because this hides the escape character ^ from the parser. However, you can use escaped quotation marks instead:

CALL SET ^"Chars=%^String:~%Skip%,%Keep%%^"
aschipfl
  • 33,626
  • 12
  • 54
  • 99