我正在尝试回显存储在变量中的字符串,但它似乎需要大量的转义。我正在尝试使用以下代码:
setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!
我想逐字回显变量grass
,所以我在输出中看到@##&!$^&%**(&)
。应该做什么?谢谢!
答案 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,
然后你不需要插入符号。