有一些方法可以避免^ 转义序列。
您可以使用延迟扩展的变量。下面是一个小批量脚本演示
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!
或者您可以使用 FOR /F 循环。从命令行:
for /f "delims=" %A in ("<html>") do @echo %~A
或来自批处理脚本:
@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A
这些方法起作用的原因是延迟扩展和 FOR 变量扩展都发生在 <、>、&、|、&&、|| 等特殊运算符被解析之后。请参阅How does the Windows Command Interpreter (CMD.EXE) parse scripts? 了解更多信息。
sin3.14 points out that pipes may require multiple escapes。例如:
echo ^^^<html^^^>|findstr .
管道需要多次转义的原因是管道的每一端都在一个新的 CMD 进程中执行,因此该行被多次解析。请参阅Why does delayed expansion fail when inside a piped block of code?,了解 Window 管道实现的许多尴尬后果。
使用管道时还有另一种方法可以避免多次转义。您可以显式实例化您自己的 CMD 进程,并用引号保护单转义:
cmd /c "echo ^<html^>"|findstr .
如果你想使用延迟扩展技术来避免转义,那么还有更多的惊喜(如果你是 CMD.EXE 设计方面的专家,你可能不会感到惊讶,但没有官方文档说明这玩意儿)
请记住,管道的每一侧都在其自己的 CMD.EXE 进程中执行,但该进程确实不继承延迟扩展状态 - 它默认为 OFF。因此,您必须显式实例化您自己的 CMD.EXE 进程并使用 /V:ON 选项来启用延迟扩展。
@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .
请注意,延迟扩展在父批处理脚本中处于关闭状态。
但是如果在父脚本中启用了延迟扩展,那么一切都会变得混乱。以下操作不起作用:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .
问题是!test!在父脚本中展开,所以新的CMD进程试图解析未受保护的<和>。
您可以转义 !,但这可能会很棘手,因为这取决于 ! 是否被引用。
如果没有引用,则需要双重转义:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .
如果引用,则使用单个转义:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .
但是有一个令人惊讶的技巧可以避免所有转义 - 封闭管道的左侧可以防止父脚本过早地扩展 !test!:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .
但我想即使这样也不是免费的午餐,因为批处理解析器在使用括号时会在末尾引入一个额外的(也许是不需要的)空间。
批处理脚本不好玩;-)