在Windows批处理文件中回显确切的字符串? [英] Echo exact string in windows batch file?
问题描述
我正在尝试回显存储在变量中的字符串,但似乎需要大量的转义。我正在尝试使用以下代码:
setlocal EnableDelayedExpansion
@echo off
setgrass = @ ##&!$ ^&%**(&)
echo!grass!
我想回应变量 grass
所以我在输出中看到一个 @ ##&!$ ^&%**(&)
。应该做什么谢谢!
echo!grass!
将始终回显当前值逐字,不需要任何逃脱。你的问题是,价值不是你认为的!当您尝试设置值时,会出现问题。
设置值的正确转义序列是
setgrass = @ ##& ^!$ ^^& %% **(&)
现在解释。您需要的信息被隐藏在如何Windows Command Interpreter(CMD.EXE)解析脚本吗?但这是有点难以追随。
您有两个问题:
1)%
每次要解析该行时,都必须以 %%
转义。报价的存在或不存在没有区别。延迟扩张状态也没有区别。
set pct =%
:: pct未定义
set pct = %%
:: pct =%
调用set pct = %%
:: pct未定义,因为该行由于CALL而被解析两次
调用set pct = %%%%
:: pct =%
2)每当它被延迟扩展阶段解析时,必须将!
直接转义为 ^!
的解析器。如果一个行在延迟展开期间的任何地方包含!
,则必须将 ^
文字转义为 ^^
。但是,对于解析器的特殊字符阶段, ^
也必须被引用或转义为 ^^
。这可能会因为CALL将任何 ^
字符加倍而变得更为复杂。 (对不起,很难描述问题,解析器很复杂!)
setlocal disableDelayedExpansion
set test = ^^
:: test = ^
settest = ^
:: test = ^
call set test = ^^
:: test = ^
::第一遍 - ^^变成^
:: CALL双打^,所以我们回到^^
:: 2nd通过 - ^^成为^
调用集test = ^
:: test = ^^因为CALL倍增。没有什么可以阻止这个。
设置test = ^ ...!
:: test = ^ ...!
::!延迟扩展被禁用时对^没有影响
setlocal enableDelayedExpansion
settest = ^
:: test = ^
:: there没有 !在线上,所以没有必要逃避引用^。
设置test = ^!
:: test =!
set test = ^^!
:: test =!
::!必须被转义,然后无引号的转义必须被转义
set var = hello
settest =!var!^^ ^!
:: test = hello ^!
:: quoted ^ literal必须被转义,因为!出现在行
set test =!var! ^^^^ ^^!
:: test = hello ^!
:: ^ literal的无引号转义本身必须被转义
::同样如此!文字
调用set test =!var! ^^^^ ^^!
:: test = hello ^!
::延迟扩展阶段发生在第一次通过
:: CALL倍增保护第二遍中的无引号^文字
调用集test =!var!^^ ^!
:: test = hello ^^!
::再次,当它通过CALL
::加倍> I'm trying to echo a string stored in a variable but it seems to require a lot of escaping. I'm trying with the following code:
setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!
I want to echo the variable grass
verbatim so I see a @##&!$^&%**(&)
in the output. What should be done? Thanks!
echo !grass!
will always echo the current value verbatim, without the need of any escaping. Your problem is, the value is not what you think it is! The problem is occurring when you are trying to SET the value.
The correct escape sequence to set your value is
set "grass=@##&^!$^^&%%**(&)"
And now for the explanation. The information you need is buried in How does the Windows Command Interpreter (CMD.EXE) parse scripts?. But it is a bit hard to follow.
You have two problems:
1) %
must be escaped as %%
for each time the line will be parsed. The presence or absence of quotes makes no difference. The delayed expansion state also makes no difference.
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) A !
literal must be escaped as ^!
whenever it is parsed by the delayed expansion phase of the parser. If a line contains !
anywhere within it during delayed expansion, then a ^
literal must be escaped as ^^
. But the ^
must also be either quoted or escaped as ^^
for the special character phase of the parser. This can be further complicated by the fact that a CALL will double up any ^
characters. (Sorry, it is very difficult to describe the problem, and the parser is complicated!)
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
这篇关于在Windows批处理文件中回显确切的字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!