Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

special chars in 'set' string substitution

92 views
Skip to first unread message

Liviu

unread,
Aug 6, 2011, 12:53:58 AM8/6/11
to
The '%variable:replace=with%' syntax fails when 'replace' starts
with an '*' asterisk or contains an '=' sign.

I've tried several variations using combinations of escaping/quoting
and 'enabledelayedexpansion', to no avail. Better luck, anyone?

Liviu


Timo Salmi

unread,
Aug 6, 2011, 9:27:56 AM8/6/11
to
On 06.08.2011 07:53 Liviu wrote:
> The '%variable:replace=with%' syntax fails when 'replace' starts
> with an '*' asterisk or contains an '=' sign.

179} How to replace an asterisk "*" in an environment variable?
http://www.netikka.net/tsneti/info/tscmd179.htm

All the best, Timo

--
Prof. Timo Salmi, Vaasa, Finland
http://www.netikka.net/tsneti/homepage.php
Useful CMD script tricks http://www.netikka.net/tsneti/info/tscmd.php

Liviu

unread,
Aug 7, 2011, 2:44:43 AM8/7/11
to
"Timo Salmi" <t...@uwasa.fi> wrote...

> On 06.08.2011 07:53 Liviu wrote:
>> The '%variable:replace=with%' syntax fails when 'replace' starts
>> with an '*' asterisk or contains an '=' sign.
>
> 179} How to replace an asterisk "*" in an environment variable?
> http://www.netikka.net/tsneti/info/tscmd179.htm

Thanks for the pointer and the linked old thread.

Neither answers however what I was actually looking for, which was
a syntax quirk to maybe take advantage of the builtin functionality,
without external programs/scripts, and avoiding char-by-char loops.

FWIW a replace-any-char-with-whatever routine is copied below.

Liviu

@rem ===================================
:: %1 = env-var holding !%1! input string
:: %2 = character to be replaced n.b. "=" equal sign must be quoted
:: %3 = replacement string, or "" to remove !%2!
:: %4 = env-var to receive the %1:%2=%3 end result

:set.subst.char
if "!errorlevel!"=="%errorlevel%" (
setlocal disabledelayedexpansion
call :set.subst.char.main %*
endlocal & set "%~2=!%~2!"
goto :eof
)
:set.subst.char.main
setlocal enabledelayedexpansion
set "string="
set /a index=0
:set.subst.char.loop
set "char=!%~1:~%index%,1!"
if "!char!"=="" goto :set.subst.char.done
if "!char!"=="%~2" (
set "string=!string!%~3"
) else (
set "string=!string!!char!"
)
set /a index+=1
goto :set.subst.char.loop
:set.subst.char.done
endlocal & set "%~4=%string%"
goto :eof
@rem ===================================

jeb

unread,
Aug 10, 2011, 6:45:05 AM8/10/11
to
On 7 Aug., 08:44, "Liviu" <lab...@gmail.c0m> wrote:
>
> Neither answers however what I was actually looking for, which was
> a syntax quirk to maybe take advantage of the builtin functionality,
> without external programs/scripts, and avoiding char-by-char loops.
>
> FWIW a replace-any-char-with-whatever routine is copied below.
>
> Liviu

A solution which search for the stars with a FOR /F loop,
so it's should be faster than a complete loop over all characters

@echo off
setlocal EnableDelayedExpansion
rem replace all "*" with "."
set "replace=."
set "var=*One**two***three"

rem Add dummy char to accept also a star in front
set "var=#!var!"
:replaceLoop
for /F "tokens=1 delims=*" %%A in ("!var!") do (
set "prefix=%%A"
set "rest=!var:*%%A=!"
if defined rest (
set "rest=!REPLACE!!rest:~1!"
set Again=1
) else set "Again="
set "var=%%A!rest!"
)
if defined again goto :replaceLoop
set "var=!var:~1!"
echo !var!
exit /b


jeb

Liviu

unread,
Aug 14, 2011, 1:55:31 AM8/14/11
to
"jeb" <xi...@gmx.de> wrote ...

>
> A solution which search for the stars with a FOR /F loop,
> so it's should be faster than a complete loop over all characters

Thanks, and something along those lines can be worked out to
replace _single_ "*" asterisks within a given string. However, the
technique cannot be expanded to cases where the search string starts
with a "*" and is more than one character long (which was in fact
the question posed originally) - for example, it can't delete "*.*" from
a string, or replace "*.111" with "*.222".

To do a full-fledged find-and-replace with arbitrary strings, one
still needs to write a manual loop (which I called "char-by-char" but
would probably be better described as "match-by-match").

> @echo off
> setlocal EnableDelayedExpansion
> rem replace all "*" with "."
> set "replace=."
> set "var=*One**two***three"
>
> rem Add dummy char to accept also a star in front
> set "var=#!var!"
> :replaceLoop
> for /F "tokens=1 delims=*" %%A in ("!var!") do (
> set "prefix=%%A"
> set "rest=!var:*%%A=!"
> if defined rest (
> set "rest=!REPLACE!!rest:~1!"
> set Again=1
> ) else set "Again="
> set "var=%%A!rest!"
> )
> if defined again goto :replaceLoop
> set "var=!var:~1!"
> echo !var!
> exit /b

FWIW the code above has some problems if !replace! itself contains
"*" asterisks, or if either string has exclamation "!" marks. Nothing
which can't be fixed, I think, just noting it for readers who may come
across this post later - including myself ;-)

Liviu


0 new messages