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.
