Page 1 of 1

Delayed Expansion and escapes

Posted: 22 May 2011 20:10
by Ed Dyreen
Is there some kind of formula to figure out how many of them you'll need instead of guessing it & trying all possibilities to display a ! ^! ^^^! ^^^^^^^! ^^^^^^^^^^^^! ^^^^^^^^^^^^^^^^^! :|

Re: Delayed Expansion and escapes

Posted: 22 May 2011 20:43
by dbenham
As long as you know how many times the character needs to be escaped it's not difficult. The total number of characters is simply a power of 2.

0 escapes = 2^0 = 1 = !
1 escape = 2^1 = 2 = ^!
2 escapes = 2^2 = 4 = ^^^!
3 escapes = 2^3 = 8 = ^^^^^^^!
etc.

One problem is it is not always obvious how many times you need to escape!

Code: Select all

@echo off
setlocal enableDelayedExpansion
prompt $g
echo on

rem Unquoted uses 2 escapes on each pass, so 2^6=64 chars initially!
set v1=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
set v2=%v1%
set v3=%v2%
set v

rem Quoted uses only 1 escape per pass, so 2^3=8 chars initially.
set "v1=^^^^^^^!"
set "v2=%v1%"
set "v3=%v2%"
set v


results:

Code: Select all

>rem Unquoted uses 2 escapes on each pass, so 2^6=64 chars initially!

>set v1=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!

>set v2=^^^^^^^!

>set v3=^!

>set v
v1=^^^^^^^^^^^^^^^!
v2=^^^!
v3=!

>rem Quoted uses only 1 escape per pass, so 2^3=8 chars initially.

>set "v1=^^^^^^^!"

>set "v2=^^^!"

>set "v3=^!"

>set v
v1=^^^!
v2=^!
v3=!

Dave Benham

Re: Delayed Expansion and escapes

Posted: 22 May 2011 21:19
by Ed Dyreen

Code: Select all

>rem Unquoted uses 2 escapes on each pass, so 2^6=64 chars initially!

>set v1=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!

>set v2=!v1!

>set v3=!v2!

>set v
v1=^^^^^^^^^^^^^^^!
v2=^^^^^^^^^^^^^^^!
v3=^^^^^^^^^^^^^^^!

>rem Quoted uses only 1 escape per pass, so 2^3=8 chars initially.

>set "v1=^^^^^^^!"

>set "v2=!v1!"

>set "v3=!v2!"

>set v
v1=^^^!
v2=^^^!
v3=^^^!
endoftest


Code: Select all

rem Unquoted uses 2 escapes on each pass, so 2^2=4 chars initially!
set v1=^^^!
set v2=!v1!
set v3=!v2!
set v

rem Quoted uses only 1 escape per pass, so 2^1=2 chars initially.
set "v1=^!"
set "v2=!v1!"
set "v3=!v2!"
set v

set "v2=!v1!" and set "v3=!v2!" don't seem to be considered a pass :!:

Code: Select all

>rem Unquoted uses 2 escapes on each pass, so 2^2=4 chars initially!

>set v1=^!

>set v2=!v1!

>set v3=!v2!

>set v
v1=!
v2=!
v3=!

>rem Quoted uses only 1 escape per pass, so 2^1=2 chars initially.

>set "v1=^!"

>set "v2=!v1!"

>set "v3=!v2!"

>set v
v1=!
v2=!
v3=!
endoftest

So that brings me to this conclusion :

Code: Select all

::--------------------------------------------------------------------------------------------------------------------------
@echo off &prompt $g &echo on
setlocal enableDelayedExpansion
rem Escapes are used when a variable is set, echoed, passed to a variable &passed as a parameter.
rem ::(
rem    ::QuickList
rem    ::(
rem       0 escapes    = 2^0 = 1    = !
rem       1 escape    = 2^1 = 2    = ^!
rem       2 escapes    = 2^2 = 4    = ^^^!
rem       3 escapes    = 2^3 = 8    = ^^^^^^^!
rem       4 escapes    = 2^4 = 16    = ^^^^^^^^^^^^^^^!
rem       5 escapes    = 2^5 = 32    = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
rem       6 escapes    = 2^6 = 64    = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
rem    ::)
rem
rem set is a pass when using set=%variable%
rem Unquoted uses 2 escapes on each pass, so 2^6=64 chars initially!
set v1=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
set v2=%v1%
set v3=%v2%
set v
rem set is a pass when using set=%variable%
rem Quoted uses only 1 escape per pass, so 2^3=8 chars initially.
set "v1=^^^^^^^!"
set "v2=%v1%"
set "v3=%v2%"
set v
rem set is only one a pass when using set=!variable!
rem Unquoted uses 2 escapes per pass, so 2^2=4 chars initially!
set v1=^^^!
set v2=!v1!
set v3=!v2!
set v
rem set is only one pass when using set=!variable!
rem Quoted uses 1 escapes per pass, so 2^1=2 chars initially.
set "v1=^!"
set "v2=!v1!"
set "v3=!v2!"
set v
@echo off &echo.endoftest &pause &exit
::--------------------------------------------------------------------------------------------------------------------------


Re: Delayed Expansion and escapes

Posted: 23 May 2011 02:36
by jeb
Hi Ed,

there are exactly three different caret phases.

The special character phase:
The caret escapes the next character and is removed, but works only outside of quotes.
Exclamation marks are not important at this phase.

The delayed phase
The caret escapes the next character, only important for exclamation marks, doesn't care about quotes.
AND this phase is only executed if there is at least on exclamation mark in the line.

The call phase:
All carets are doubled, don't care about quotes. This seems to be false, as you normally didn't see double quotes, but this is only, because they are normally removed by the next special character phase.

Samples

Code: Select all

setlocal enableDelayedExpansion
echo without exclam ^^^^ "^^^^"
echo with    exclam ^^^^ "^^^^" !
set "^=one"
set "^^=two"
set "caret=^"
call echo %%!caret!%% caret
call call call call echo ^^^^ "^^^^"


Output

Code: Select all

without exclam ^^ "^^^^"
with    exclam ^ "^^"
two caret
^^ "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"

jeb