echo !grass!
zawsze będzie wyświetlać bieżącą wartość dosłownie, bez potrzeby jakiegokolwiek odskoku. Twój problem polega na tym, że wartość nie jest taka, jak myślisz! Problem występuje, gdy próbujesz ustawić wartość.
Prawidłowa sekwencja ucieczki, aby ustawić wartość jest
set "[email protected]##&^!$^^&%%**(&)"
A teraz do wyjaśnienia. Potrzebne informacje są pochowane w How does the Windows Command Interpreter (CMD.EXE) parse scripts?. Ale jest to trochę trudne do naśladowania.
mieć dwa problemy:
1) %
musi być ocalałem jako %%
za każdym razem, gdy linia będzie analizowany. Obecność lub brak cytatów nie robi różnicy. Opóźniony stan ekspansji również nie ma znaczenia.
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) !
dosłownym musi być dodana jako ^!
gdy jest on przetwarzany w opóźnionej fazy rozprężania parser. Jeśli linia zawiera !
w dowolnym jej miejscu podczas opóźnionego rozszerzenia, wówczas literał ^
musi zostać zmieniony jako ^^
. Ale ^
musi być również cytowany lub unikany jako ^^
dla fazy znaków specjalnych parsera. Może to być dodatkowo komplikowane przez fakt, że CALL podwoi dowolne znaki ^
. (Niestety, jest to bardzo trudne do opisania problemu, a parser jest skomplikowany!)
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
Niezłe wyjaśnienie. Dzięki! – user1077213
Czy istnieje lista znaków, które wymagają ucieczki? Takich jak '*', '(' itp. – user1077213