在Windows命令提示符中转义尖括号

108

我需要将包含尖括号(< 和 >)的字符串输出到 Windows 机器上的文件。基本上我想做的是:

echo some string < with angle > brackets >>myfile.txt

但这样不起作用,因为命令解释器会混淆尖括号。我可以像这样引用整个字符串:

echo "some string < with angle > brackets" >>myfile.txt

但是这样我的文件中就有了我不想要的双引号。

类Unix系统下转义括号也行不通:

echo some string \< with angle \> brackets >>myfile.txt

有什么好的建议吗?


6
引用语也将被回显。 - dalle
6个回答

183

Windows转义字符是^,原因未知。

echo some string ^< with angle ^> brackets >>myfile.txt

10
反斜杠用于路径名,双引号用于包含有空格的文件名,所以剩下可选的字符不多了。 - James Curran
这也适用于其他字符,如和号(&),谢谢。 - tenfour
2
非常好!echo some string ^< with angle ^> brackets >>con 的结果是:_some string < with angle > brackets_。 - Ross Bradbury
1
这是因为原始的PC-DOS使用反斜杠作为路径分隔符,为了向后兼容。 - James John McGuire 'Jahmic'
我怀疑这并不是完全随机的。我猜想他们想使用一个在正常文本中不太可能出现的字符,以避免产生容易避免但不需要的字符转义。 - David A. Gray

29

是的,官方转义字符是 ^,但要小心,因为有时需要使用三个 ^ 字符。这只是有时需要:

C:\WINDOWS> echo ^<html^>
<html>

C:\WINDOWS> echo ^<html^> | sort
The syntax of the command is incorrect.

C:\WINDOWS> echo ^^^<html^^^> | sort
<html>

C:\WINDOWS> echo ^^^<html^^^>
^<html^>

从这个无聊的事情中学到的一个技巧是使用除了 echo 之外的命令进行输出,并用双引号引用:

C:\WINDOWS> set/p _="<html>" <nul
<html>
C:\WINDOWS> set/p _="<html>" <nul | sort
<html>
请注意,这将不会保留提示文本前的空格。

2
请参见我的回答的第二部分,了解为什么管道需要多个转义符的解释。 - dbenham
1
在Azure DOS/Kudu控制台中,还需要使用三个“^^^”来转义命令。 - lionello
我发现当你想通过Azure CLI在Azure密钥保管库中存储包含尖括号的值时,这确实是必需的。 - Jaap

10

有一些方法可以避免使用^转义序列。

您可以使用延迟扩展的变量。以下是一个小的批处理脚本演示:

@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 .

但我想即使如此也不是一顿免费的午餐,因为当使用括号时,批处理解析器会在结尾处引入一个额外的(或许是不想要的)空格。
批处理脚本编写起来真有趣 ;-)

4
为了在Windows上使用特殊字符,例如">",您需要在其前面放置一个特殊的转义字符才能用echo打印出来。
例如:
echo A->B

'>'需要用'^'转义,否则无法正常工作:

 echo A-^>B

这里有一个简短的批处理文件,可以打印出基本的特殊字符及其转义序列。另外还可以参考转义序列。图片如下:enter image description here

0
转义括号和Unix一样也行不通:
echo some string \< with angle \> brackets >>myfile.txt
反斜杠将被认为是绝对路径名的开头。

2
相对于当前驱动器盘符的绝对路径名... ;) - dalle
在echo命令的文本中,反斜杠不被视为绝对路径名的起始位置--它只是普通文本,可以被管道发送到任何地方。例如,echo \ 可以按预期工作。但是,"\ "将成为命令行转义字符的不良选择,因为每个需要路径或文件名的命令/程序都必须键入\\ - BrainSlugs83
1
这个回答并没有针对那个含糊不清的问题提供解决方案。 - G-.

-3

您也可以使用双引号来转义特殊字符...

echo some string "<" with angle ">" brackets >>myfile.txt

5
不起作用。 echo some string "<" with angle ">" brackets >>con 的结果是: _some string "<" with angle ">" brackets_,但 OP 希望的是 _some string < with angle > brackets_。 - Ross Bradbury

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接