2012-03-18 62 views
5

Tôi đang cố gắng để echo một chuỗi được lưu trữ trong một biến nhưng có vẻ như yêu cầu rất nhiều thoát. Tôi đang cố gắng với đoạn mã sau:Echo chuỗi chính xác trong tập tin batch của Windows?

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

Tôi muốn echo biến grass đúng nguyên văn vì vậy tôi thấy một @##&!$^&%**(&) trong đầu ra. Cần làm gì? Cảm ơn!

Trả lời

12

echo !grass! sẽ luôn lặp lại nguyên văn giá trị hiện tại mà không cần phải thoát. Vấn đề của bạn là, giá trị không phải là điều bạn nghĩ! Sự cố xảy ra khi bạn đang cố gắng đặt giá trị.

Các dãy thoát đúng để thiết lập giá trị của bạn là

set "[email protected]##&^!$^^&%%**(&)" 

Và bây giờ để giải thích. Thông tin bạn cần được chôn cất trong How does the Windows Command Interpreter (CMD.EXE) parse scripts?. Nhưng nó là một chút khó khăn để làm theo.

Bạn có hai vấn đề:

1) % phải được thoát ra như %% cho mỗi lần dòng sẽ được phân tích. Sự hiện diện hay vắng mặt của dấu ngoặc kép không có sự khác biệt. Trạng thái mở rộng bị trì hoãn cũng không có sự khác biệt.

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) Một ! đen phải được thoát ra như ^! bất cứ khi nào nó được phân tách bởi các giai đoạn mở rộng chậm trễ của các phân tích cú pháp. Nếu một dòng có chứa ! bất kỳ vị trí nào trong phạm vi đó trong khi mở rộng bị trì hoãn, thì phải xóa một ký tự ^ bằng ^^. Nhưng ^ cũng phải được trích dẫn hoặc thoát ra dưới dạng ^^ cho giai đoạn ký tự đặc biệt của trình phân tích cú pháp. Điều này có thể phức tạp hơn bởi thực tế là một CALL sẽ tăng gấp đôi bất kỳ ký tự ^ nào. (Rất tiếc, rất khó để mô tả vấn đề và trình phân tích cú pháp phức tạp!)

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

Giải thích hay. Cảm ơn! – user1077213

+0

Có danh sách các nhân vật cần thoát không? Chẳng hạn như '*', '(' vv? – user1077213

2

Như đã nói, đó chỉ là nhiệm vụ.
Bạn có thể sử dụng thoát như dbenham cho thấy, nó là cần thiết như EnableDelayedExpansion là hoạt động trong khi bạn thiết lập giá trị.
Vì vậy, bạn cần phải thoát khỏi dấu chấm than và dấu mũ phải được thoát vì có một dấu chấm than trong dòng, dấu ngoặc kép là vô ích trong tình huống đó.
Nhưng bạn cũng có thể đặt giá trị trước khi bạn kích hoạt EnableDelayedExpansion,
Sau đó, bạn không cần phải có dấu mũ.

+0

Ví dụ: dạng thoát của '@ ## &! $^&% ** (&)' trông như thế nào nếu bạn đặt giá trị trước khi bật mở rộng trễ ? – user1077213

+2

@ user1077213 - Miễn là giá trị được trích dẫn, thì chỉ cần% được tăng gấp đôi: 'set 'grass = @ ## &! $^& %% ** (&)" '. Không có dấu ngoặc kép bạn cần nhiều lần thoát: 'set grass = @ ##^&! $ ^^^ & %% ** (^ &)' sẽ hoạt động miễn là không nằm trong khối được chặn. Nếu dấu ngoặc đơn đang hoạt động, thì đóng ') 'cũng phải được thoát:' set grass = @ ##^&! $ ^^^ & %% ** (^ & ^) '. – dbenham

+0

Điều đó có ý nghĩa. Cảm ơn! :) – user1077213

Các vấn đề liên quan