I need to match or replace an asterisk * in a batch environmental variable using only native Windows commands. Is this possible?

The easy answer is no.

The problem that you’re encountering stems from the fact that the asterisk * is a special character when used with the SET search and replace method. It matches multiple characters in a limited, but still useful, way. You can learn about that here.

The hard answer is Yes!

I will provide you with two solutions. One an incomplete solution but elegent,
the other complete and inelegent.

Both methods will search for * and replace it with an x.
Both methods will both search and modify the following string:

*love*

The first method that comes to mind is using a ‘FOR /L’ statement, and requires that you know how many characters long the environmental variable is.

::Major Edit::

I thought I knew the various maximum size strings of environmental variables, but dbenham has taken me to school, shown me a kick-in-the-behind length function, and in the mean time completely reversed my opinions of the two solutions I’m presenting.

Other than for the Windows 95/98/ME limitation of a 256 Character maximum environmental variable size. It seems that all versions of Windows using CMD.EXE have a limitation of 8,192 characters, well below what the documentation suggests.

Both versions require delayed environmental variable expansion, but for two different reasons. One because I’m operating inside a FOR statement. The other because you cannot put a % pair inside another % pair because the command processor matches the second % that it encounters to the first one it encounters, but we need to use a variable inside another variable expression. (You’ll see.)

This solution uses the strLen function (in line 3) from DosTips.com that can be found Here. Just slap it into a file called strLen.bat and be amazed at it’s speed!

Solution 1: (FOR /L Solution) :: Preferred Solution ::

setlocal ENABLEDELAYEDEXPANSION
set nam=*love*
rem calling strLen
call :strLen nam len
for /l %%x in (0,1,%len%) do if not "!nam:~%%x,1!"=="" if "!nam:~%%x,1!"=="*" (
    set /a plusone=%%x+1
    for /l %%y in (!plusone!, 1, !plusone!) do (
        set nam=!nam:~0,%%x!x!nam:~%%y!
    )
)
echo %nam%
ENDLOCAL

I think this is a quick and elegant solution It could be sped up by adding the contents of strLen.bat to the routine, but I wanted no confusion as to the author.

If you, for some reason, do not wish to use strLen, then the next quickest method would probably use a GOTO loop.

Solution 2: (Goto Solution)

setlocal ENABLEDELAYEDEXPANSION
set nam=*love*
set num=0

:loop
    set /a plusone=%num%+1
    if "!nam:~%num%,1!"=="*" set nam=!nam:~0,%num%!x!nam:~%plusone%!
    set /a num=%num%+1
if not "!nam:~%num%,1!"=="" goto :loop

echo %nam%
EndLocal

Special thanks to dbenham for pointing out the strLen function. It works faster than any batch based function has a right to!

Leave a Comment