有一些方法可以避免^
转义序列。
您可以使用延迟扩展的变量。下面是一个小批量脚本演示
@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 变量扩展都发生在特殊运算符(如<
, >
, &
, , |
, &&
, )||
被解析之后。请参阅Windows 命令解释器 (CMD.EXE) 如何解析脚本?了解更多信息。
sin3.14 指出管道可能需要多次转义。例如:
echo ^^^<html^^^>|findstr .
管道需要多次转义的原因是因为管道的每一侧都在一个新的 CMD 进程中执行,因此该行被多次解析。请参阅为什么在管道代码块中延迟扩展失败?用于解释 Window 的管道实现的许多尴尬后果。
使用管道时,还有另一种方法可以避免多次转义。您可以显式实例化您自己的 CMD 进程,并用引号保护单转义:
cmd /c "echo ^<html^>"|findstr .
如果你想使用延迟扩展技术来避免逃逸,那么还有更多的惊喜(如果你是 CMD.EXE 设计方面的专家,你可能不会感到惊讶,但没有官方的 MicroSoft 文档解释这些东西)
请记住,管道的每一侧都在其自己的 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 进程试图解析 unprotected<
和>
.
您可以逃避!
,但这可能会变得棘手,因为这取决于是否!
引用了 。
如果没有引用,则需要双重转义:
@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 .
但我想即使这样也不是免费的午餐,因为批处理解析器在使用括号时会在末尾引入一个额外的(也许是不需要的)空间。
不是批处理脚本的乐趣;-)