Does anyone know how to replace a * symbol in a string?

Microsoft Windows
Post Reply
User avatar
MigrationUser
Posts: 336
Joined: 2021-Jul-12, 1:37 pm
Contact:

Does anyone know how to replace a * symbol in a string?

Post by MigrationUser »

11 Aug 2010 15:50
anandr


I came into trouble with the Variable Edit/Replace syntax of the SET command (https://ss64.com/nt/syntax-replace.html).
My batch script receives file mask as a parameter.
While processing thoe files I need to save a log to file, whose name contains the mask.
But "*" and "?" are not allowed in file name and I'm trying to replace "*" with "_all_" string.
I do this:

Code: Select all

::here I store the mask
set FileMask="%~1"
::here I try to modify the mask to put it into log file name
set SuggestedFileName=%FileMask:*=_all_%
All I get is

Code: Select all

=_all_% was unexpected at this time.
Because in this syntax the "*" is used to replace/delete character string and everything before it.

How it is possible to replace "*" itself?

Thanks

P.S.
These lines do not work either:

Code: Select all

set SuggestedFileName=%FileMask:^*=_all_%
call set SuggestedFileName=%%FileMask:*=_all_%%
Everything will be OK at the end. If it is not OK -- it is not the end.

----------------------------

#2 11 Aug 2010 20:05
RG


Sorry,
When "str1" begins with an asterisk it indicates that it will match everything from the beginning of the expanded output to the first occurrence of the remaining portion of str1.
For example, the line below would work if your mask is always of the format: FileName.*, which is probably not much help other than an explanation.

Code: Select all

set SuggestedFileName=%FileMask:.*=._all_%
Last edited by RG (11 Aug 2010 20:45)

Windows Shell Scripting and InstallShield

----------------------------

#3 11 Aug 2010 23:23
RG


This will work although it will not catch multiple consecutive *

Code: Select all

set SuggestedFileName=
call :Replace "%~1"
echo.SuggestedFileName=%SuggestedFileName%
goto :eof

:Replace
rem %1=String
rem Need next line to handle leading *
for /F "tokens=* delims=*" %%a in ("%~1") DO if not "%~1"=="%%a" set SuggestedFileName=_all_%SuggestedFileName%
for /F "tokens=1* DELIMS=*" %%a in ('echo.%~1') do (
   (CALL set SuggestedFileName=%SuggestedFileName%%%a)
   rem Line below will also handle trailing * if needed.  Be careful of that if you simplify it.
   if not "%%a%%b"=="%~1" call set SuggestedFileName=%SuggestedFileName%_all_& call :Replace "%%b"
)
goto :eof
Last edited by RG (11 Aug 2010 23:25)

Windows Shell Scripting and InstallShield

----------------------------

#4 12 Aug 2010 10:03
bluesxman


Another method.

Code: Select all

@echo off

set "in.string=qwertyuiop*asdfghjkl"
set "replace=*"
set "with=_all_"
set "out.string="

REM current position within IN.STRING
set i=0
REM length of REPLACE string
set L=1

set in.string

call :loop

set out.string

pause

goto :EOF

:loop

REM grab the next set of characters in the string
call set "char=%%in.string:~%i%,%L%%%"

REM if they are blank, we've reached the end of the string
if "%char%" EQU "" goto :EOF

if "%char%" EQU "%replace%" (
    REM if they match the REPLACE string, add the WITH string to OUT.STRING
    set "out.string=%out.string%%with%"
) ELSE (
    REM otherwise just add them to OUT.STRING
    set "out.string=%out.string%%char%"
)

REM increment our position in IN.STRING for the next loop
set /a i+=L

call :loop
Not heavily tested.

cmd | *sh | ruby | chef

----------------------------

#5 12 Aug 2010 16:14
jumper

Code: Select all

@echo off&setlocal enabledelayedexpansion

set "in.str=*qwe*rt**yuiop*asdfghj*kl*"

set in.str

set ou.str=&for /f "tokens=1* delims=][" %%a in ('
  "%comspec% /u /cecho:"%in.str%"|more|find /n /v """
 ') do (set "b=%%b"&if "%%b"=="*" (set $=_all_) else set "$=%%b"
set ou.str=!ou.str!!$!)
set "ou.str=%ou.str:~1,-1%"

set ou.str
pause
goto:eof
Last edited by jumper (12 Aug 2010 16:15)

----------------------------

#6 12 Aug 2010 16:50
bluesxman


Nice work jumper.

An interesting method for breaking the string into single characters -- took me a while to figure out what you're doing there.

Might I suggest the following refinements to allow for file names containing "&", "[" or "]"?

Code: Select all

@echo off

set "in.str=*qw!e*rt**yu&iop*a[[[s][]dfghj*kl*"

set in.str

set ou.str=&for /f "tokens=* delims=" %%b in ('
  %comspec% /u /cecho:"%in.str%" ^|more ^|find /v """"
 ') do (
    if "%%b" EQU "*" (
        call set "ou.str=%%ou.str%%_all_"
    ) else (
        call set "ou.str=%%ou.str%%%%b"
    )
)

set ou.str
pause
goto:eof
cmd | *sh | ruby | chef

----------------------------

#7 12 Aug 2010 18:19
jumper


Re: Does anyone know how to replace a * symbol in a string?
bluesxman wrote:

Nice work jumper.

An interesting method for breaking the string into single characters -- took me a while to figure out what you're doing there.

Might I suggest the following refinements to allow for file names containing "&", "[" or "]"?

Code: Select all

    @echo off

    set "in.str=*qw!e*rt**yu&iop*a[[[s][]dfghj*kl*"

    set in.str

    set ou.str=&for /f "tokens=* delims=" %%b in ('
      %comspec% /u /cecho:"%in.str%" ^|more ^|find /v """"
     ') do (
        if "%%b" EQU "*" (
            call set "ou.str=%%ou.str%%_all_"
        ) else (
            call set "ou.str=%%ou.str%%%%b"
        )
    )

    set ou.str
    pause
    goto:eof
thank's bluesxman your code is better,

Another method with SED:

Code: Select all

@echo off

Set "Path=X:\Program Files\GnuWin32\bin;%path%" #  set environment variable

set "in.str=*qw!e*rt**yu&iop*a[[[s][]dfghj*kl*" # your string
set in.str

echo "%in.str%" | sed  "s=^\x22\|\x22.$==g;s=\x2a=_all_=g"
http://gnuwin32.sourceforge.net/packages/sed.htm

Last edited by jumper (12 Aug 2010 18:19)

----------------------------

#8 13 Aug 2010 11:56
anandr


Thank you, jumper and bluesxman!
That is amazing, guys!

Could you, please, explain why this command breaks string into characters?

Code: Select all

%comspec% /u /cecho:"%in.str%" ^|more
I can not understand why "/u" switch + "more" behave this way?
Does this mean that "more" can not handle unicode characters properly and treats zero-characters as EndOfLine?

Whatever it is you are incredible.
I'm taking off my hat to you!

Everything will be OK at the end. If it is not OK -- it is not the end.

----------------------------

#9 13 Aug 2010 12:46
bluesxman
anandr wrote:

Does this mean that "more" can not handle unicode characters properly and treats zero-characters as EndOfLine?
It looks that way to me.

It's certainly an interesting quirk. I hope to exploit it frequently in future now that jumper has brought it to my attention!

cmd | *sh | ruby | chef

----------------------------

#10 14 Aug 2010 17:49
RG


WOW! That is really clever jumper. And thanks for the extra touch bluesxman.
Life just got easier! I will use that a lot! Sure beats my solution, which was plenty of work and was not bullet proof.
Thanks Guys.

Windows Shell Scripting and InstallShield

----------------------------

#11 14 Aug 2010 18:44
Simon Sheppard


Its an interesting technique, but if I feed it some real unicode characters strange conversions happen:

Code: Select all

C:\>%comspec% /c echo £¥ƒ*?$¢|more
£¥ƒ*?$¢


C:\>%comspec% /u /c echo £¥ƒ*?$¢|more
ú
Ñ
Æ☺*
¼ $
ó


----------------------------

#12 14 Aug 2010 19:15
carlos


I think that you can improve line.
From:

Code: Select all

%comspec% /u /cecho:"%in.str%" ^|more
To:

Code: Select all

%comspec% /u /d /x /v:off /cecho:"!in.str!" ^|more
With d you avoid the execution of autorun registry, with x you active extensions, and with v:off active delayed expansion, this is for echoing special characters.
Post Reply