在Windows批处理文件中回显精确字符串?

时间:2012-03-18 10:10:09

标签: batch-file escaping

我正在尝试回显存储在变量中的字符串,但它似乎需要大量的转义。我正在尝试使用以下代码:

setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!

我想逐字回显变量grass,所以我在输出中看到@##&!$^&%**(&)。应该做什么?谢谢!

2 个答案:

答案 0 :(得分:13)

echo !grass!将始终逐字回显当前值,而无需任何转义。你的问题是,价值不是你想象的那样!当您尝试设置值时,问题就出现了。

设置值的正确转义序列是

set "grass=@##&^!$^^&%%**(&)"

现在解释一下。您需要的信息隐藏在How does the Windows Command Interpreter (CMD.EXE) parse scripts?中。但它有点难以理解。

你有两个问题:

1)每次解析该行时,%必须以%%进行转义。引号的存在与否都没有区别。延迟扩张状态也没有区别。

 set pct=%
 :: pct is undefined

 set pct=%%
 :: pct=%

 call set pct=%%
 :: pct is undefined because the line is parsed twice due to CALL

 call set pct=%%%%
 :: pct=%

2)只要解析器的延迟扩展阶段解析!个文字,就必须将其转义为^!。如果某行在延迟展开期间的任何位置包含!,则必须将^字面值转义为^^。但是,对于解析器的特殊字符阶段,^也必须引用或转义为^^。由于CALL会使任何^个字符加倍,这可能会进一步复杂化。 (抱歉,描述问题非常困难,解析器很复杂!)

setlocal disableDelayedExpansion

set test=^^
:: test=^

set "test=^"
:: test=^

call set test=^^
:: test=^
:: 1st pass - ^^ becomes ^
:: CALL doubles ^, so we are back to ^^
:: 2nd pass - ^^ becomes ^

call set "test=^"
:: test=^^ because of CALL doubling. There is nothing that can prevent this.

set "test=^...!"
:: test=^...!
:: ! has no impact on ^ when delayed expansion is disabled

setlocal enableDelayedExpansion

set "test=^"
:: test=^
:: There is no ! on the line, so no need to escape the quoted ^.

set "test=^!"
:: test=!

set test=^^!
:: test=!
:: ! must be escaped, and then the unquoted escape must be escaped

set var=hello
set "test=!var! ^^ ^!"
:: test=hello ^ !
:: quoted ^ literal must be escaped because ! appears in line

set test=!var! ^^^^ ^^!
:: test=hello ^ !
:: The unquoted escape for the ^ literal must itself be escaped
:: The same is true for the ! literal

call set test=!var! ^^^^ ^^!
:: test=hello ^ !
:: Delayed expansion phase occurs in the 1st pass only
:: CALL doubling protects the unquoted ^ literal in the 2nd pass

call set "test=!var! ^^ ^!"
:: test=hello ^^ !
:: Again, there is no way to prevent the doubling of the quoted ^ literal
:: when it is passed through CALL

答案 1 :(得分:2)

正如dbenham所说,这只是作业 您可以使用dbenham显示的转义,因为在设置值时EnableDelayedExpansion处于活动状态是必要的。
因此,您需要转义感叹号并且必须转义插入符号,因为行中有一个感叹号,在这种情况下引号无效。
但您也可以在之前设置值,以激活EnableDelayedExpansion,
然后你不需要插入符号。