有一些方法可以避免使用^
转义序列。
您可以使用延迟扩展的变量。以下是一个小的批处理脚本演示:
@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指出管道可能需要多次转义。例如:
echo ^^^<html^^^>|findstr .
管道需要多次转义的原因是每个管道的两侧都在新的CMD进程中执行,所以该行被解析多次。参见
为什么延迟扩展在代码块内使用管道时失败?以了解Windows管道实现的许多尴尬后果的解释。
还有另一种方法可以避免在使用管道时多次转义。您可以显式地实例化自己的CMD进程,并用引号保护单个转义符。
cmd /c "echo ^<html^>"|findstr .
如果你想使用延迟扩展技术来避免转义字符,那么会有更多的意外(如果你是CMD.EXE设计专家,可能不会感到惊讶,但是没有官方的微软文档解释这些内容)。
请记住,管道的每一侧都在它自己的CMD.EXE进程中执行,但是该进程
不继承延迟扩展状态-它默认为关闭。因此,你必须显式地实例化自己的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 .
但我想即使如此也不是一顿免费的午餐,因为当使用括号时,批处理解析器会在结尾处引入一个额外的(或许是不想要的)空格。
批处理脚本编写起来真有趣 ;-)