我需要将包含尖括号(<和>)的字符串回显到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
想法?
由于某种原因,Windows转义字符是^.
echo some string ^< with angle ^> brackets >>myfile.txt
确实,官方的逃脱角色是^
,但要小心,因为有时你需要三个 ^
角色.这只是有时候:
C:\WINDOWS> echo ^ C:\WINDOWS> echo ^ | sort The syntax of the command is incorrect. C:\WINDOWS> echo ^^^ | sort C:\WINDOWS> echo ^^^ ^
这个废话的一个技巧是使用除echo
输出之外的命令并使用双引号引用:
C:\WINDOWS> set/p _=""C:\WINDOWS> set/p _=""
请注意,这不会保留提示文本上的前导空格.
有一些方法可以避免^
转义序列.
您可以使用具有延迟扩展的变量.下面是一个小批量脚本演示
@echo off setlocal enableDelayedExpansion set "line=" echo !line!
或者你可以使用FOR/F循环.从命令行:
for /f "delims=" %A in ("") do @echo %~A
或者从批处理脚本:
@echo off for /f "delims=" %%A in ("") do echo %%~A
这些方法工作的原因是因为这两个延迟扩展和FOR变量扩展特种作业等之后发生<
,>
,&
,|
,&&
,||
被解析.请参阅Windows命令解释器(CMD.EXE)如何解析脚本?了解更多信息.
sin3.14指出管道可能需要多次逃逸.例如:
echo ^^^|findstr .
管道需要多次转义的原因是管道的每一侧都在新的CMD过程中执行,因此该行被多次解析.请参阅为什么在管道代码块内部延迟扩展失败?解释Window的管道实现的许多尴尬后果.
使用管道时还有另一种避免多次转义的方法.您可以显式实例化您自己的CMD进程,并使用引号保护单个转义:
cmd /c "echo ^"|findstr .
如果你想使用延迟扩展技术来避免逃逸,那么还有更多的惊喜(如果你是CMD.EXE设计方面的专家,你可能不会感到惊讶,但是没有正式的MicroSoft文档可以解释这些东西)
请记住,管的每一面在自己的CMD.EXE过程被执行,但这一过程不会不继承推迟扩张状态-它默认为关闭.因此,您必须显式实例化您自己的CMD.EXE进程并使用/ V:ON选项启用延迟扩展.
@echo off setlocal disableDelayedExpansion set "line=" cmd /v:on /c echo !test!|findstr .
请注意,父批处理脚本中的延迟扩展为OFF.
但是如果在父脚本中启用了延迟扩展,那么所有地狱都会破裂.以下就不能正常工作:
@echo off setlocal enableDelayedExpansion set "line=" REM - the following command fails cmd /v:on /c echo !test!|findstr .
问题是,!test!
在父脚本扩展,所以新的CMD进程试图解析未受保护的<
和>
.
你可以逃脱!
,但这可能会变得棘手,因为它取决于是否!
引用.
如果没有引用,则需要双重转义:
@echo off setlocal enableDelayedExpansion set "line=" cmd /v:on /c echo ^^!test^^!|findstr .
如果引用,则使用单个转义:
@echo off setlocal enableDelayedExpansion set "line=" cmd /v:on /c "echo ^!test^!"|findstr .
但是有一个令人惊讶的技巧可以避免所有的转义 - 封闭管道的左侧会阻止父脚本!test!
过早地扩展:
@echo off setlocal enableDelayedExpansion set "line=" (cmd /v:on /c echo !test!)|findstr .
但我想即使这不是免费的午餐,因为批处理解析器在使用括号时会在末尾引入额外的(可能不需要的)空间.
Aint批处理脚本乐趣;-)