2012-03-18 14 views

Odpowiedz

12

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

Niezłe wyjaśnienie. Dzięki! – user1077213

+0

Czy istnieje lista znaków, które wymagają ucieczki? Takich jak '*', '(' itp. – user1077213

2

Jak dbenham powiedział, że to tylko przypisanie.
Można użyć funkcji escaping, jak pokazano dbenham, jest to konieczne, ponieważ EnableDelayedExpansion jest aktywne podczas ustawiania wartości.
Dlatego trzeba uciec od wykrzyknika, a karetka musi zostać usunięta, ponieważ w linii znajduje się jeden wykrzyknik, w tym przypadku cytaty są bezużyteczne.
Ale możesz również ustawić wartość przed aktywujesz EnableDelayedExpansion,
Wtedy nie potrzebujesz opiekunek.

+0

Więc na przykład, jak wyglądałaby uciekająca forma '@ ## &! $^&% ** (&)' jeśli ustawisz wartość przed włączeniem opóźnionej ekspansji ? – user1077213

+2

@ user1077213 - Tak długo jak wartość jest cytowana, tylko% musi zostać podwojona: 'set" grass = @ ## &! $^& %% ** (&) "'. Bez cytatów potrzebujesz wiele escapes: 'set grass = @ ##^&! $ ^^^ & %% ** (^ &)' będzie działało tak długo, jak długo nie będzie w bloku parentetyzowanym. Jeśli nawiasy są aktywne, to zamykanie ') 'musi również zostać zmienione:' set grass = @ ##^&! $ ^^^ & %% ** (^ & ^) '. – dbenham

+0

To ma sens. Dzięki! :) – user1077213

Powiązane problemy