Supposing one wants to replace certain substrings by exclamation marks using the substring replacement syntax while delayed expansion is enabled, they have to use immediate (normal) expansion, because the parser cannot distinguish between !
s for expansion and literal ones.
However, why does one have to escape exclamation marks in the replacement string? And why is it not necessary and even disruptive when exclamation marks in the search string are escaped?
The following script replaces !
s in a string by `
and in reverse order afterwards, so I expect the result to be equal to the initial string (which must not contain any back-ticks on its own of course):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem This is the test string:
set "STRING=string!with!exclamation!marks!"
set "DELOFF=%STRING%"
set "DELOFF=%DELOFF:!=`%"
set "DELOFF=%DELOFF:`=!%"
setlocal EnableDelayedExpansion
set "DELEXP=!STRING!"
set "DELEXP=%DELEXP:!=`%"
set "DELEXP=%DELEXP:`=!%"
echo(original string: !STRING!
echo(normal expansion: !DELOFF!
echo(delayed expansion: !DELEXP!
endlocal
endlocal
exit /B
This result is definitely not what I want, the last string is different:
original string: string!with!exclamation!marks! normal expansion: string!with!exclamation!marks! delayed expansion: stringexclamation
As soon as take the line...:
set "DELEXP=%DELEXP:`=!%"
....and replace the !
by ^!
there, hence escaping the exclamation mark in the replace string, the result is exactly what I expect:
original string: string!with!exclamation!marks! normal expansion: string!with!exclamation!marks! delayed expansion: string!with!exclamation!marks!
When I try other escaping combinations though (escape the exclamation mark in both the replace and the search string, or in the latter only), the result is again the aforementioned unwanted one.
I walked through the post How does the Windows Command Interpreter (CMD.EXE) parse scripts? but I could not find an explanation to that behaviour, because I learned the normal (or immediate, percent) expansion is accomplished long before delayed expansion occurs and any exclamation marks are even recognised. Also caret recognition and escaping seems to happen afterwards. In addition, there are even quotation marks around the strings that usualy hide carets from the parser.