How to avoid "~" in set / replace command?

I am trying to replace all ~ instances with {~} in a script package so that VBScript does not assume that I want to press Enter when I pass it sendKeys, however the variable continues to get replaced with the literal string intended to replace it.

For instance,

 rem Intended function; rem input = Hello~world. rem output = Hello{~}world. 

However, each time it either does nothing or sets refVar to the literal string refVar:~={~} .

Here is what I tried:

 set refVar=!refVar:~={~}! rem Also set refVar=%refVar:~={~}% rem and... set refVar=%refVar:^~=^{^~^}% rem and of course; set refVar=!refVar:^~=^{^~^}! rem and even: set "pre=~" set "post={~}" set refVar=%refVar:!pre!=!post!% rem and the same set commands with; set refVar=!refVar:%pre%=%post%! 

Am I missing a way to avoid this? I am sure that this is due to the fact that ~ is a positional symbol in a similar command.

I understand that there is a way to fix this in VBScript, but it prevents me from having a limitation without visible workarounds for me.

+6
source share
3 answers

I suggest, perhaps, a simpler solution to replace each tilde character in the string of environment variables with a tilde in curly braces than Dennis van Gils , which is also a great fit for this task.

 @echo off set "TestVar=hello~world." echo TestVar has value: %TestVar% call :SpecialReplace "TestVar" echo TestVar has value: %TestVar% goto :EOF rem The subroutine below expects the name of an environment variable as rem parameter. The subroutine does nothing if called without parameter. rem Also nothing is done if specified environment variable is not defined. rem Each tilde character in value of this environment variable is replaced rem by {~} by this subroutine. rem Note: This subroutine can be also easily modified to replace other rem special characters like the equal sign by a different string which rem can be also no string in case of special character should be removed. rem Just modify Search and Replace variables for a different replace. But rem be aware of more code must be changed if search string is longer than rem one character. Length of replace string does not matter on code below. :SpecialReplace if "%~1" == "" exit /B setlocal EnableDelayedExpansion set "VarName=%~1" set "VarValue=!%VarName%!" if "!VarValue!" == "" endlocal & exit /B set "NewValue=" set "Search=~" set "Replace={~}" :ReplaceLoop if "!VarValue:~0,1!" == "!Search!" ( set "NewValue=!NewValue!!Replace!" ) else ( set "NewValue=!NewValue!!VarValue:~0,1!" ) set "VarValue=!VarValue:~1!" if not "!VarValue!" == "" goto ReplaceLoop endlocal & set "%VarName%=%NewValue%" & exit /B 

To understand the commands used and how they work, open a command prompt window, run the following commands there, and carefully read all the help pages displayed for each command.

  • call /?
  • echo /?
  • endlocal /?
  • exit /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?

And see also the answer to a Single line with multiple commands using a Windows batch file to understand how two lines work with multiple commands with the same ampersand between commands.


The variant above with the extended SpecialReplace routine, now supporting variable search and replacing the strings specified as the second and third parameters, as suggested by Dennis van Gils .

 @echo off set "TestVar=hello~world." echo TestVar has value: %TestVar% call :SpecialReplace "TestVar" "~" "{~}" echo TestVar has value: %TestVar% goto :EOF rem The subroutine below expects the name of an environment variable as rem first parameter. The subroutine does nothing if called without parameter. rem Also nothing is done if specified environment variable is not defined. rem The second parameter must be the search string. The subroutine does rem nothing if there is no second parameter which can be also just one rem or two double quotes enclosed in double quotes. rem The third parameter is an optional replace string. Without a third rem parameter all occurrences of search string are removed from value rem of the specified environment variable. rem With just one or two double quotes in double quotes as search string rem no replace string can be defined because command processor does not rem parse the quote strings as most would expect it. But """ or """" as rem search string with no replace string works and results in removing rem all double quotes or all occurrences of two double quotes. :SpecialReplace if "%~1" == "" exit /B setlocal EnableDelayedExpansion set "VarName=%~1" set "VarValue=!%VarName%!" if "!VarValue!" == "" endlocal & exit /B set "NewValue=" set "Search=%~2" if "!Search!" == "" endlocal & exit /B set "Replace=%~3" set "Length=0" :GetLength if "!Search:~%Length%,1!" == "" goto ReplaceLoop set /A Length+=1 goto GetLength :ReplaceLoop if "!VarValue:~0,%Length%!" == "!Search!" ( set "NewValue=!NewValue!!Replace!" set "VarValue=!VarValue:~%Length%!" ) else ( set "NewValue=!NewValue!!VarValue:~0,1!" set "VarValue=!VarValue:~1!" ) if not "!VarValue!" == "" goto ReplaceLoop endlocal & set "%VarName%=%NewValue%" & exit /B 
+2
source

So, I did the digging, and it seems like it is really very hard. However, I found this one that solves the problem by providing us this as code:

 @echo off set "input=Hello~world." echo input: %input% call :wavereplacer "%input%" {tilde} output set output=%output:{tilde}={~}% echo output: %output% pause ::your own code should be above this. goto :eof :wavereplacer String Replacer [RtnVar] setlocal rem the result of the operation will be stored here set "result=#%~1#" set "replacer=%~2" call :strlen0.3 result wl call :strlen0.3 replacer rl :start set "part1=" set "part2=" rem splitting the string on two parts for /f "tokens=1* delims=~" %%w in ("%result%") do ( set "part1=%%w" set "part2=%%x" ) rem calculating the count replace strings we should use call :strlen0.3 part1 p1l call :strlen0.3 part2 p2l set /a iteration_end=wl-p1l-p2l rem creating a sequence with replaced strings setlocal enableDelayedExpansion set "sequence=" for /l %%i in (1,1,%iteration_end%) do ( set sequence=!sequence!%replacer% ) endlocal & set "sequence=%sequence%" rem adjust the string length set /a wl=wl+iteration_end*(rl-1) rem replacing for the current iteration set result=%part1%%sequence%%part2% rem if the second part is empty the task is over if "%part2%" equ "" ( set result=%result:~1,-1% goto :endloop ) goto :start :endloop endlocal & if "%~3" neq "" (set %~3=%result%) else echo %result% exit /b :strlen0.3 StrVar [RtnVar] setlocal EnableDelayedExpansion set "s=#!%~1!" set "len=0" for %%A in (2187 729 243 81 27 9 3 1) do ( set /A mod=2*%%A for %%Z in (!mod!) do ( if "!s:~%%Z,1!" neq "" ( set /a "len+=%%Z" set "s=!s:~%%Z!" ) else ( if "!s:~%%A,1!" neq "" ( set /a "len+=%%A" set "s=!s:~%%A!" ) ) ) ) endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len% exit /b 

This cannot replace ~ with {~} immediately, you need to use temporary substitution, in this case {tilde}

+4
source
 @ECHO Off SETLOCAL ENABLEDELAYEDEXPANSION SET "input=hello~world" SET "xhead=!input:%input:*~=%=!" SET "output=!input:%xhead%=%xhead:~0,-1%{~}!" ECHO %input% --^> %output% GOTO :EOF 

This works if there is exactly one ~ and that it is not a start or end character.

+1
source

All Articles