echo !grass!
restituisce sempre il valore corrente letteralmente, senza la necessità di alcuna escaping. Il tuo problema è, il valore non è quello che pensi che sia! Il problema si verifica quando si sta tentando di impostare il valore.
la correttezza sequenza di escape per impostare il valore è
set "[email protected]##&^!$^^&%%**(&)"
E ora per la spiegazione. Le informazioni necessarie sono sepolte in How does the Windows Command Interpreter (CMD.EXE) parse scripts?. Ma è un po 'difficile da seguire.
Si hanno due problemi:
1) %
deve essere sfuggito come %%
per ogni volta che la linea sarà analizzato. La presenza o l'assenza di citazioni non fa differenza. Anche lo stato di espansione ritardata non fa differenza.
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 !
letterale deve essere sfuggito come ^!
ogniqualvolta viene analizzata dalla fase di espansione ritardata del parser. Se una riga contiene !
in qualsiasi punto al suo interno durante l'espansione ritardata, è necessario eseguire il escape di un valore letterale ^
come ^^
. Ma il ^
deve anche essere quotato o salvato come ^^
per la fase di carattere speciale del parser. Ciò può essere ulteriormente complicato dal fatto che una CHIAMATA raddoppierà qualsiasi carattere ^
. (Ci dispiace, è molto difficile da descrivere il problema, e il parser è complicato!)
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
Bella spiegazione. Grazie! – user1077213
Esiste un elenco di caratteri che devono essere salvati? Ad esempio, '*', '(' ecc. – user1077213