Batch file 替换字符串中需要转义感叹号,但搜索字符串中不需要转义感叹号(启用延迟扩展的子字符串替换)?
假设要在启用语法时使用感叹号替换某些子字符串,它们必须使用立即(正常)扩展,因为解析器无法区分Batch file 替换字符串中需要转义感叹号,但搜索字符串中不需要转义感叹号(启用延迟扩展的子字符串替换)?,batch-file,replace,cmd,escaping,delayedvariableexpansion,Batch File,Replace,Cmd,Escaping,Delayedvariableexpansion,假设要在启用语法时使用感叹号替换某些子字符串,它们必须使用立即(正常)扩展,因为解析器无法区分s表示扩展和文本 但是,为什么必须在替换字符串中转义感叹号?当搜索字符串中的感叹号被转义时,为什么没有必要,甚至没有破坏性呢 以下脚本将替换s,然后按相反顺序输入,因此我希望结果等于初始字符串(当然,初始字符串本身不能包含任何反勾号): 这个结果肯定不是我想要的,最后一个字符串不同: 只要你接电话……: set "DELEXP=%DELEXP:`=!%" ..并更换由^此处,因此转义替换字符串中的感叹
代码>s表示扩展和文本
但是,为什么必须在替换字符串中转义感叹号?当搜索字符串中的感叹号被转义时,为什么没有必要,甚至没有破坏性呢
以下脚本将替换通过`
在字符串中输入code>s,然后按相反顺序输入,因此我希望结果等于初始字符串(当然,初始字符串本身不能包含任何反勾号):
这个结果肯定不是我想要的,最后一个字符串不同:
只要你接电话……:
set "DELEXP=%DELEXP:`=!%"
..并更换代码>由^代码>此处,因此转义替换字符串中的感叹号,结果正是我所期望的:
但是,当我尝试其他转义组合时(在replace和search字符串中转义感叹号,或者仅在search字符串中转义感叹号),结果还是前面提到的不需要的结果
我浏览了这篇文章,但我找不到对这种行为的解释,因为我了解到,正常(或即时,百分比)扩展在延迟扩展发生之前就已经完成了,甚至可以识别出任何感叹号。此外,插入符号识别和逃逸似乎发生在之后。此外,字符串周围甚至有引号,通常会对解析器隐藏插入符号。实际上,对于子字符串替换本身,不需要转义。它只在后面的解析阶段才有必要。这就是为什么:
但是,为什么必须在替换字符串中转义感叹号
问题是,即时(正常,%
)扩展是在相当早期的阶段完成的,而延迟扩展(!
),顾名思义,是作为最后的步骤之一完成的。因此,立即展开的字符串也会经过延迟展开阶段。作为证明,将变量VAR
设置为值!X
和X
到0
,然后执行echo%VAR%
,这样您将得到Value0
。
但回到最初的问题,当使用立即子字符串替换时,替换字符串是扩展值的一部分,因此它也会经过延迟扩展阶段。因此,必须转义文字感叹号,以免被延迟的扩展占用。这意味着替换本身不需要转义,它实际上是在之后完成的,因此包含转义的给定替换字符串按字面意义应用
当搜索字符串中的感叹号被转义时,为什么没有必要,甚至没有破坏性呢
由于插入符号识别和转义是在立即展开后发生的,因此搜索字符串按字面处理。此外,搜索字符串被替换,因此不包括在立即子字符串替换的输出中,因此它不会通过延迟扩展阶段
让我们看一下原始示例(仅摘录):
替换集“DELEXP=%DELEXP:!=`%”
搜索代码>。结果值是带有感叹号的string`
使用set“DELEXP=%DELEXP:^!=`%”
将搜索^代码>按字面意思,因此当然不会找到任何实例(因此保留了原始字符串中的所有文字!
,最后通过延迟扩展进行处理)
替换设置“DELEXP=%DELEXP:`=!%”
将`
替换为代码>完美,结果字符串是字符串!具有感叹号马克代码>,但这些都会被随后的延迟扩展所消耗
转义的替换%DELEXP:`=^!%代码>将`
替换为^代码>字面意思,因此结果是string^!与^!感叹号^!马克^代码>;转义随后在延迟扩展阶段进行处理,结果是literal
和返回字符串字符串!具有感叹号马克代码>最后
据《华盛顿邮报》报道,还有第二个逃逸阶段,即延迟扩张阶段。这一点适用于原始问题中的示例,因为第一次转义(在特殊字符识别阶段)由于周围的引号而被禁用(省略此类转义将导致需要双重转义,如^!
)
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!
set "STRING=string!with!exclamation!marks!"
setlocal EnableDelayedExpansion
set "DELEXP=!STRING!"
set "DELEXP=%DELEXP:!=`%"
set "DELEXP=%DELEXP:`=!%"
echo(delayed expansion: !DELEXP!
endlocal