命令提示符中的转义尖括号

我需要将包含尖括号(< 和 >)的字符串回显到 Windows 计算机上的文件。基本上我想做的是:
echo some string < with angle > brackets >>myfile.txt

由于命令解释器会与尖括号混淆,所以不能正常工作。我可以像这样引用整个字符串:
echo "some string < with angle > brackets" >>myfile.txt

但是在我的文件中有我不想要的双引号。

省略 ala unix 中的括号也不起作用:
echo some string \< with angle \> brackets >>myfile.txt

有什么想法吗?

49195 次浏览

The Windows escape character is ^, for some reason.

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

Escaping the brackets ala unix doesn't work either:

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

The backslash would be considered the start of a absolute pathname.

You can also use double quotes to escape special characters...

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

True, the official escape character is ^, but be careful because sometimes you need three ^ characters. This is just sometimes:

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^>

One trick out of this nonsense is to use a command other than echo to do the output and quote with double quotes:

C:\WINDOWS> set/p _="<html>" <nul
<html>
C:\WINDOWS> set/p _="<html>" <nul | sort
<html>

Note that this will not preserve leading spaces on the prompt text.

There are methods that avoid ^ escape sequences.

You could use variables with delayed expansion. Below is a small batch script demonstration

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!

Or you could use a FOR /F loop. From the command line:

for /f "delims=" %A in ("<html>") do @echo %~A

Or from a batch script:

@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A

The reason these methods work is because both delayed expansion and FOR variable expansion occur after special operators like <, >, &, |, &&, || are parsed. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for more info.


sin3.14 points out that pipes may require multiple escapes. For example:

echo ^^^<html^^^>|findstr .

The reason pipes require multiple escapes is because each side of the pipe is executed in a new CMD process, so the line gets parsed multiple times. See Why does delayed expansion fail when inside a piped block of code? for an explanation of many awkward consequences of Window's pipe implementation.

There is another method to avoid multiple escapes when using pipes. You can explicitly instantiate your own CMD process, and protect the single escape with quotes:

cmd /c "echo ^<html^>"|findstr .

If you want to use the delayed expansion technique to avoid escapes, then there are even more surprises (You might not be surprised if you are an expert on the design of CMD.EXE, but there is no official MicroSoft documentation that explains this stuff)

Remember that each side of the pipe gets executed in its own CMD.EXE process, but the process does not inherit the delayed expansion state - it defaults to OFF. So you must explicitly instantiate your own CMD.EXE process and use the /V:ON option to enable delayed expansion.

@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .

Note that delayed expansion is OFF in the parent batch script.

But all hell breaks loose if delayed expansion is enabled in the parent script. The following does not work:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .

The problem is that !test! is expanded in the parent script, so the new CMD process is trying to parse unprotected < and >.

You could escape the !, but that can get tricky, because it depends on whether the ! is quoted or not.

If not quoted, then double escape is required:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .

If quoted, then a single escape is used:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .

But there is a surprising trick that avoids all escapes - enclosing the left side of the pipe prevents the parent script from expanding !test! prematurely:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .

But I suppose even that is not a free lunch, because the batch parser introduces an extra (perhaps unwanted) space at the end when parentheses are used.

Aint batch scripting fun ;-)

In order to use special characters, such as '>' on Windows with echo, you need to place a special escape character before it.

For instance

echo A->B

will no work since '>' has to be escaped by '^':

 echo A-^>B

See also escape sequences. enter image description here

There is a short batch file, which prints a basic set of special character and their escape sequences.