2012-03-18 16 views
5

Sto provando a echo una stringa memorizzata in una variabile ma sembra richiedere un sacco di escape. Sto cercando con il seguente codice:Echo stringa esatta nel file batch di Windows?

setlocal EnableDelayedExpansion 
@echo off 
set "[email protected]##&!$^&%**(&)" 
echo !grass! 

Voglio fare eco alla variabile grass testualmente così vedo un @##&!$^&%**(&) nell'output. Cosa dovrebbe essere fatto? Grazie!

risposta

12

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

Bella spiegazione. Grazie! – user1077213

+0

Esiste un elenco di caratteri che devono essere salvati? Ad esempio, '*', '(' ecc. – user1077213

2

Come ha detto dbenham, è solo l'assegnazione.
È possibile utilizzare l'escaping come mostrato da dbenham, è necessario poiché EnableDelayedExpansion è attivo mentre si imposta il valore.
Pertanto è necessario sfuggire al punto esclamativo e il cursore deve essere sfuggito perché c'è un punto esclamativo nella linea, le virgolette sono inutili in quella situazione.
Ma è possibile anche impostare il valore prima di si attiva EnableDelayedExpansion,
Quindi non sono necessari i segni di omissione.

+0

Quindi, ad esempio, come apparirebbe la forma di escape di '@ ## &! $^&% ** (&)' se si imposta il valore prima di abilitare l'espansione ritardata ? – user1077213

+2

@ user1077213 - Finché il valore è quotato, solo il% deve essere raddoppiato: 'set" grass = @ ## &! $^& %% ** (&) "'. Senza le virgolette necessarie molti escape: 'set grass = @ ##^&! $ ^^^ & %% ** (^ &)' funzionerà finché non è all'interno di un blocco tra parentesi Se parentesi sono attive, quindi la chiusura ') 'deve anche essere escapato:' set grass = @ ##^&! $ ^^^ & %% ** (^ & ^) '. – dbenham

+0

Questo ha senso. Grazie! :) – user1077213

Problemi correlati