2012-03-18 15 views

Respuesta

12

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 
+0

Buena explicación. ¡Gracias! – user1077213

+0

¿Hay una lista de caracteres que necesitan escaparse? Tales como '*', '(' etc.? – user1077213

2

Como dijo dbenham, es sólo la asignación.
Puede usar el escape como mostró dbenham, es necesario porque EnableDelayedExpansion está activo mientras establece el valor.
Por lo tanto, debe evitar el signo de exclamación y se debe evitar el símbolo de intercalación, ya que hay un signo de admiración en la línea, las comillas son inútiles en esa situación.
Pero también podría establecer el valor antes de activar EnableDelayedExpansion,
Entonces no necesita los caret.

+0

Así, por ejemplo, cómo sería la forma de escape de '@ ## &! $^&% ** (&) 'si configura el valor antes de habilitar la expansión retrasada ? – user1077213

+2

@ user1077213 - Siempre que se cite el valor, solo se debe duplicar el%: 'establecer" grass = @ ## &! $^& %% ** (&) "'. Sin las comillas que necesita muchos escapes: 'set grass = @ ##^&! $ ^^^ & %% ** (^ &)' funcionará siempre que no esté dentro de un bloque entre paréntesis. Si los paréntesis están activos, entonces el cierre ') 'también debe ser escapado:' set grass = @ ##^&! $ ^^^ & %% ** (^ & ^) '. – dbenham

+0

Eso tiene sentido. ¡Gracias! :) – user1077213

Cuestiones relacionadas