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

use*_*213 5 escaping batch-file

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

setlocal EnableDelayedExpansion
@echo off
set "grass=@##&!$^&%**(&)"
echo !grass!
Run Code Online (Sandbox Code Playgroud)

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

dbe*_*ham 13

echo !grass!将始终逐字回显当前值,而无需任何转义.你的问题是,价值不是你想象的那样!当您尝试设置值时,会发生此问题.

设置值的正确转义序列是

set "grass=@##&^!$^^&%%**(&)"
Run Code Online (Sandbox Code Playgroud)

现在来解释一下.您需要的信息隐藏在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=%
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)