echo !grass!
siempre hará eco del valor actual palabra por palabra, sin necesidad de ningún escape. Tu problema es que el valor no es lo que crees que es. El problema ocurre cuando intentas ESTABLECER el valor.
La secuencia de escape correcta para establecer su valor es
set "[email protected]##&^!$^^&%%**(&)"
Y ahora para la explicación. La información que necesita está enterrada en How does the Windows Command Interpreter (CMD.EXE) parse scripts?. Pero es un poco difícil de seguir.
Usted tiene dos problemas:
1) %
debe ser escapado como %%
por cada vez que se analiza la línea. La presencia o ausencia de citas no hace diferencia. El estado de expansión retardada tampoco hace diferencia.
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 debe ser escapado como ^!
cada vez que se analiza por la fase de expansión retardada del analizador. Si una línea contiene !
en cualquier lugar dentro de ella durante la expansión retrasada, se debe escapar un literal ^
como ^^
. Pero el ^
también debe ser entre comillas o escapado como ^^
para la fase de caracteres especiales del analizador. Esto se puede complicar aún más por el hecho de que una llamada duplicará cualquier ^
caracteres. (Lo siento, es muy difícil de describir el problema, y el analizador se complica!)
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
Buena explicación. ¡Gracias! – user1077213
¿Hay una lista de caracteres que necesitan escaparse? Tales como '*', '(' etc.? – user1077213