i have a request for theorical knowledge purpose only in Windows Batch scripting.
Today my question is about preparing the value of a local string loc_str
INSIDE A BLOCK OF PARENTHESIS and WITHOUT ENABLING DELAYED EXPANSION, in order to return it to a local scope that enables variable expasion (or eventually to prepare it for an incoming local for loop with in("%loc_str%")
if nasty characters in loc_str have been properly escaped before).
We assume that loc_str
contains at least one ^
and one !
and do not contain double quotes. Lets consider the following code:
@echo off
setlocal disabledelayedexpansion
set "flag_dde_prev=%flag_dde%" & set "flag_dde=!"
(
set "loc_str=Hello^^^ planet!!!! ^^Earth^"
if not defined flag_dde_prev (
call set "out_str=%%loc_str:^=^^%%"
set out_str
call set "out_str=%%out_str:^=^^%%"
set out_str
)
)
endlocal & set "str=%out_str%"
set str
As you know the local flags flag_{dde, dde_prev}
are used to test the type of the calling and current scopes. Typically they're both defined at the beginning of a block setlocal..endlocal
. The flag_dde
is equal to !
if the current scope disables variable expansion, or is undefined
if the current scope enables it. The local value of flag_dde_prev
is the inherited value of flag_dde
in the calling scope.
What we must do here is to escape all ^
and !
to prepare the return of out_str
with %..%
to the calling scope when this latter enable variable expansion (ie when flag_dde_prev
is defined). Two substitutions ^=^^
then !=^!
with a simple set
would be enough, but being inside a block (..) forces us to use the call set
statement. Unfortunatly the caret ^
is not replaced in the same way they are in a scope that enables variable expansion.
Precisely, the first substitution ^=^^
doubles even sequences of carets, but does not double odd ones (it doubles them minus one).
Then, the second substitution !=^!
replace each !
with ^^!
.
To sump up,
loc_str=Hello^^^ planet!!!! ^^Earth^ ;init
out_str=Hello^^^^^ planet!!!! ^^^^Earth^ ;1st substitution ^=^^
out_str=Hello^^^^^ planet^^!^^!^^!^^! ^^^^Earth^ :2nd substitution !=^!
^=^^
seems to be reversible with ^^=^
if done BEFORE !=^!
only.
If ^^=^
is done after !=^!
then sequences of ^
not preceeding !
are modified only.
If ^^=^
is done after !=^!
i didn't find a way to replace the sequences of ^^
before each "
.
It behaves like a sequence ^^
before !
is the atomic unreplacable one, longer caret sequences can be replaced but i couldn't obtain ^!
whatever i tried.
The same problem is quite easy to solve when variable expansion is enabled, even with nasty strings containing quotes by replacing ""
by "
at first (jeb already talked about this in another thread). For example if locs_tr
doesn't contain quotes, the substitutions would be the following:
set "out_str=!loc_str:^=^^^^!" ;1st substitution, multiplicates the number of ^ by 4 as expected
call set "out_str=%%out_str:^!=^^^!%%" ! ;2nd substitution, replaces each ! by ^^!
set "out_str=!out_str:^^=^!" ;3rd substitution required, replaces each ^^ by ^ to divide by 2 the total number of ^
So my question is simple:
Is there a way using substitution IN THE EXACT SAME CONTEXT (ie no call
) to obtain the desired prepared output value for out_str
, so it can be returned safely to a scope that enables delayed expansion ?
The prepared output value should double the number of ^
and add ^
before each !
ie:
out_str=Hello^^^^^^ planet^!^!^!^! ^^^^Earth^^
Note that's my question is for theorical knowledge purpose ONLY. Indeed calling a label to do the two substitutions with a simple set
is the reasonable way to proceed.