2011-11-24 29 views
6

Tên biến môi trường do người dùng xác định Windows có thể chứa bất kỳ ký tự nào trừ =.Cú pháp nào sẽ kiểm tra nếu một tên biến chứa dấu cách được xác định?

Có thể bao gồm các ký tự đặc biệt bằng cách thoát chúng. Một phương pháp đơn giản hơn là chỉ cần đính kèm toàn bộ biểu thức SET trong dấu ngoặc kép. Ví dụ:

set "A weird & "complex" variable=My value" 
set A weird ^& "complex" variable=My value 

Cả hai biểu thức trên đều cho kết quả tương tự. Tên biến là A weird & "complex" variable và giá trị là My value

các NẾU xây dựng ĐỊNH NGHĨA được sử dụng để kiểm tra xem một biến được định nghĩa. Báo giá không hoạt động cho thử nghiệm này, các ký tự đặc biệt trong tên (bao gồm dấu ngoặc kép) phải được thoát.

set "A&B=value" 
if defined A^&B echo This works 
if defined "A&B" echo This does not work 

Thử nghiệm thoát ở trên hoạt động tốt. Bài kiểm tra được trích dẫn không hoạt động

Nhưng làm cách nào để kiểm tra xem một biến chứa không gian tồn tại?

set "A B=value" 
if defined A^ B echo this does not work! 

Có vẻ như ở trên sẽ hiệu quả nhưng không được!

Tôi đang tìm câu trả lời KHÔNG liên quan đến việc mở rộng biến bằng cách sử dụng% A B% hoặc! A B!

Trả lời

5

Câu hỏi xen kẽ (Tôi thích câu hỏi cơ sở cú pháp này).

Rõ ràng là bạn biết cách kiểm tra nó với việc mở rộng bị trì hoãn và các tham số FOR cũng hoạt động.

@echo off 
setlocal 
set "AAA BBB=value" 
set ""AAA BBB"=" 
set "AAA=" 
for %%a in ("AAA BBB") do if defined %%~a echo FOR: This works 

setlocal EnableDelayedExpansion 
set "varname=AAA BBB" 
if defined !varname! echo Delayed: This works 

if defined %varname% (echo percent: Never comes here 
) ELSE (echo percent: Never comes here ?) 

if defined AAA^ BBB (echo escape1: Never comes here 
) ELSE (echo escape1: fails) 

set AAA=Hello 
if defined AAA^ BBB ( 
    echo escape2: It only test for AAA the BBB will be "removed" 
) ELSE (echo escape2: fails) 

set "space= " 
if defined AAA!space!BBB echo inject space: This works 

if defined "AAA BBB" (echo Quote1: Never comes here 
) ELSE (echo Quote1: Fails) 

set ""AAA BBB"=value" 
if defined "AAA BBB" echo Quote2: This works, it checks for "AAA BBB" with quotes 

Trong opionion của tôi, trong ví dụ escape2 phân tích cú pháp đầu tiên tách dòng vào thẻ theo cách này:
<if> <defined> <AAA BBB> <echo .... Nhưng đồng thời thực hiện các nếu định nghĩa nó quét lại các <AAA BBB> thẻ nên nó chỉ nhận được AAA.
Bạn không thể tiêm một lối thoát thứ hai như AAA^^^ BBB vì điều này chỉ tìm kiếm các biến có tên AAA^

Tôi không thể nhìn thấy một giải pháp mà không trì hoãn/CHO, như thoát của không gian luôn luôn thất bại.

EDIT: Nó cũng có thể được giải quyết với SET <varname>
Các giải pháp của ijprest sử dụng lệnh SET để kiểm tra biến mà không cần thoát khỏi varname.
Nhưng nó cũng cho thấy hành vi interessting với không gian bên trong và ở phần cuối của một varname.

Có vẻ như tuân thủ những quy tắc:
SET varname tìm kiếm cho tất cả các biến bắt đầu với varname, nhưng trước tiên nó loại bỏ tất cả các ký tự sau khi nhân vật không gian cuối cùng của varname, và nó loại bỏ tất cả các không gian hàng đầu.
Vì vậy, bạn không thể tìm kiếm các biến có bắt đầu bằng dấu cách (nhưng cũng hơi phức tạp để tạo ra một varname).

Hành vi tương tự cũng hoạt động nếu variablename được bao gồm trong dấu ngoặc kép, nhưng sau đó tồn tại thêm một quy tắc.
Trước hết hãy xóa tất cả các ký tự sau dấu ngoặc kép cuối cùng, nếu có ít nhất hai dấu ngoặc kép. Sử dụng văn bản bên trong dấu ngoặc kép và sử dụng "dấu cách".

Mẫu.

set " abc def ghi" junk junk 
*** 1. removes the junk 
set " abc def ghi" 
*** 2. removes the quotes 
set  abc def ghi 
*** 3. removes all after the last space, and the trailing spaces 
set abc def 
*** Search all variables beginning with abc def 
+0

FOR /! Trì hoãn! giải pháp không rõ ràng khi tôi cần ngủ. Tôi đã nghĩ về nó khi tôi thức dậy, nhưng bạn đã có một câu trả lời xuất sắc! :) – dbenham

+0

Phân tích * escape2 * của bạn rất thú vị. Tuy nhiên, một cơ hội khác để đưa một bình luận vào một tuyên bố – dbenham

0

Một cách khác là chuyển nhượng lại cho một biến khác (một mà không có khoảng trắng) và thử nghiệm rằng. Xem tại đây:

rem Prepare ONLY variable 'a b' 
set "a b=123" 
echo [a b]=%a b% 

rem This will ouput: [a b] is defined 
set var=%a b% 
if defined var (
    echo [a b] is defined 
) else (
    echo [a b] is not defined 
) 

rem This will output: [c d] is not defined 
set var=%c d% 
if defined var (
    echo [c d] is defined 
) else (
    echo [c d] is not defined 
) 
+0

Tất nhiên là có hiệu quả, nhưng yêu cầu cuối cùng của câu hỏi ban đầu của tôi nói rằng tôi đang tìm câu trả lời KHÔNG sử dụng% A B% hoặc! A B !. (BTW, gán! A B! An toàn hơn nhiều. Việc gán% A B% có thể thất bại tùy theo nội dung) – dbenham

3

Tôi cũng thích loại câu hỏi này! :)

Đây là một giải pháp khả thi tôi đã đưa ra ... sử dụng SET bản thân để kiểm tra sự tồn tại, và sử dụng kết quả ERRORLEVEL:

set "A B=foo" 
set A B >nul 2>nul&& echo 1. This works 
set "A B ">nul 2>nul&& echo 2. This works 

set "A weird & "complex" variable=foo" 
set A weird ^& "complex" variable >nul 2>nul&& echo 3. This works 
set "A weird & "complex" variable ">nul 2>nul&& echo 4. This works 

Lưu ý rằng chỉ có các công trình này nếu các biến của bạn là độc đáo theo nghĩa là không có tên biến nào là tiền tố của một tên khác. Nếu không, bạn có nguy cơ dương tính giả, vì hành vi mặc định của SET là hiển thị tất cả các biến bắt đầu với thông số bạn vượt qua. Nếu điều này có thể là trường hợp, bạn có thể lọc kết quả với findstr:

set "A B=" 
set "A B C=foo" 
set "A B ">nul 2>nul&& echo 5. Failed (false positive) 
set "A B "|findstr /B /L /C:"A B=" >nul||echo 6. This works (no false positive) 

Ngoài ra, không gian đơn trailing sau tên biến dường như được yêu cầu. Không có nó, SET thường phân tích sai đầu vào. Thật kỳ lạ, nếu bạn thêm một khoảng trống thừa giữa "2> nul" và "& &" trong trường hợp # 3 nó ngừng hoạt động (trừ khi bạn xóa không gian trước "> nul") ... lạ.

+0

+1 Giải pháp tốt với việc bổ sung FINDSTR. Tôi đã nghĩ đến bài kiểm tra SET và từ chối nó, nhưng không nghĩ thêm FINDSTR. Tôi vẫn thích giải pháp của jeb bởi vì nó không yêu cầu đường ống hoặc lệnh bên ngoài, vì vậy nó nhanh hơn. – dbenham

+0

Phát hiện rất thú vị về không gian thừa yêu cầu bất kỳ biến nào bắt đầu với "a" phù hợp. Các dấu ngoặc kép là không cần thiết. 'đặt số b' không thành công. 'thiết lập một tác phẩm b '. 'đặt một số b ' không thành công! @ jeb - bất kỳ ý tưởng gì đang xảy ra ở đây? – dbenham

+0

Tôi thêm nhận xét vào [answer] (http://stackoverflow.com/a/8257295/463115) về hành vi SET-space – jeb

-2

tôi làm điều đó bằng cách định nghĩa một lá cờ như TRUE nếu cần thiết ...

rem /* sample code */ 
set VAR_SET= 
if <some condition> set VAR_SET=TRUE&set VAR=this data has spaces 

rem /* test for VAR_SET using 'if defined' */ 
if defined VAR_SET (
    rem /* do something with the other data in the variable %VAR% */ 
) 

rem /* clear the flag */ 
set VAR_SET= 
+1

Bạn chưa trả lời câu hỏi - bạn hoàn toàn bỏ lỡ vấn đề. – dbenham

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