假设在启用延迟扩展的情况下,想要使用子字符串替换语法用感叹号替换某些子字符串,他们必须使用立即(正常)扩展,因为解析器无法区分扩展的 s 和文字的扩展。!
但是,为什么必须在替换字符串中转义感叹号?为什么搜索字符串中的感叹号被转义时没有必要甚至破坏性?
以下脚本将!
字符串中的 s 替换为 s`
并以相反的顺序替换,因此我希望结果等于初始字符串(当然,它本身不能包含任何反引号):
@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
这个结果肯定不是我想要的,最后一个字符串不一样:
original string: string!with!exclamation!marks! normal expansion: string!with!exclamation!marks! delayed expansion: stringexclamation
只要走线...:
set "DELEXP=%DELEXP:`=!%"
....并在那里替换!
,^!
因此在替换字符串中转义感叹号,结果正是我所期望的:
original string: string!with!exclamation!marks! normal expansion: string!with!exclamation!marks! delayed expansion: string!with!exclamation!marks!
但是,当我尝试其他转义组合时(在替换和搜索字符串中转义感叹号,或仅在后者中转义),结果再次是上述不需要的。
我浏览了这篇文章Windows 命令解释器 (CMD.EXE) 如何解析脚本?但我找不到这种行为的解释,因为我知道正常(或立即,百分比)扩展是在延迟扩展发生之前很久就完成的,甚至可以识别任何感叹号。插入符号的识别和转义似乎也在之后发生。此外,通常在解析器中隐藏插入符号的字符串周围甚至还有引号。