我想要输出一个存储在变量中的字符串,但貌似需要进行大量转义。我尝试使用以下代码:
setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!
我想要直接输出变量 grass
的值,以便在输出中看到 @##&!$^&%**(&)
。应该怎么做?谢谢!
我想要输出一个存储在变量中的字符串,但貌似需要进行大量转义。我尝试使用以下代码:
setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!
我想要直接输出变量 grass
的值,以便在输出中看到 @##&!$^&%**(&)
。应该怎么做?谢谢!
echo !grass!
将始终直接输出当前值,无需进行任何转义。你的问题在于,该值并非你所认为的那个值!问题出现在你尝试设置该值时。
正确的转义序列以设置你的值是:
set "grass=@##&^!$^^&%%**(&)"
现在让我来解释一下。你需要的信息被深埋在《Windows命令解释器(CMD.EXE)如何解析脚本?》这篇文章中,但它有点难以理解。
你有两个问题:
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
正如dbenham所说,这只是一个赋值操作。
你可以像dbenham展示的那样使用转义字符,因为在设置变量值时EnableDelayedExpansion处于活动状态。
因此,你需要转义感叹号,并且由于该行中有一个感叹号,所以插入符号也必须进行转义,引号在这种情况下是无用的。
但是,你也可以在激活EnableDelayedExpansion之前设置变量的值,
然后你就不需要插入符号了。
@##&!$^&%**(&)
的转义形式会是什么样子? - user1077213set "grass=@##&!$^&%%**(&)"
。如果没有引号,则需要多个转义符:set grass=@##^&!$^^^&%%**(^&)
只要不在括号块内就可以工作。如果括号处于活动状态,则还必须转义右括号)
:set grass=@##^&!$^^^&%%**(^&^)
。 - dbenham
*
,(
等等。 - user1077213