4

Is someone able to explain how cmd handles carats, in the following examples?

C:\>set ^^=test

C:\>echo %^%
test

C:\>echo ^%^%
test

C:\>echo %^^%
%^%

I figured that %^% would be handled as simply %%. I assume that the variable expansion is handled before the carat is considered, however that is a half arsed answer to a question that I'm sure could be more eloquently explained.

In batch -

@echo off
set ^^=test
echo %^%
echo ^%^%
echo %^^%

--

C:\>test.bat
test
test
ECHO is off.
unclemeat
  • 4,691
  • 4
  • 22
  • 49

2 Answers2

3

It is because the order of how Batch processes each command line. Simply put, the variable expansion is performed before analyzing special characters. That is why the carat is consumed by the variable expansion before being removed as an escape character. This is also why percent characters have to be escaped by themselves %% instead of the standard carat ^ escape character.

Phase/order

1) Phase(Percent):

  • A double %% is replaced by a single %
  • Expansion of argument variables (%1, %2, etc.)
  • Expansion of %var%, if var does not exists replace it with nothing
  • For a complete explanation read this from dbenham Same thread: percent expansion

1.5) Remove all <CR> (CarriageReturn 0x0d) from the line

2) Phase(Special chars, " <LF> ^ & | < > ( ): Look at each character

  • If it is a quote (") toggle the quote flag, if the quote flag is active, the following special characters are no longer special: ^ & | < > ( ).
  • If it is a caret (^) the next character has no special meaning, the caret itself is removed, if the caret is the last character of the line, the next line is appended, the first charater of the next line is always handled as escaped character.
    • <LF> stops the parsing immediately, but not with a caret in front

For a full and great explanation (seriously bookmark this link!) see the answers here:

Community
  • 1
  • 1
David Ruhmann
  • 10,344
  • 2
  • 32
  • 46
3

Additionally to the answer of David Ruhrmann...

You create a variable named ^, as the parser will escape the second caret and remove the first one in the statement set ^^=test.

As David explained, the percent expansion phase is the first phase so it can expand even strange expressions like a <CR> character, but it's also the cause why you can't build a multiline percent expansion.
First the percents are expanded (and fails as there is only one) and then the mutliline caret is used to append the next line.

echo %va^
r%

But really confusing is the next caret example

set "^=one caret"
set "^^=two carets"
echo "%^%"
call echo "%%^%%"

The output is

"one caret"
"two carets"

It's because carets will be doubled by a CALL

jeb
  • 70,992
  • 15
  • 159
  • 202