2009-05-22 115 views
21

Làm cách nào để phân tích cú pháp đối số dòng lệnh được hiểu là đường dẫn? args [] chứa chuỗi sẽ được tự động tham gia nếu họ được trích dẫn, ví dụ:C# Phân tích dòng lệnh của các đường dẫn được trích dẫn và tránh các ký tự thoát

example.exe một hai "ba bốn"

args[0] = one 
args[1] = two 
args[2] = three four 

Tuy nhiên, args [] sẽ không sở hữu phân tích cú pháp "C: \ Example \ "làm đối số. Thay vào đó, nó sẽ cung cấp đối số là "C: \ Example" "(kèm thêm dấu ngoặc kép.) Điều này là do dấu gạch chéo ngược trong đường dẫn được coi là ký tự thoát và do đó báo giá kết thúc mà người dùng đã cung cấp trên lệnh line trở thành một phần của cuộc tranh luận

.eg:.

một example.exe "C: \ InputFolder" "C: \ OutuptFolder \"

args[0] = one 
args[1] = C:\InputFolder" 
args[2] = C:\OutputFolder" 

một kludge dễ dàng có thể là:

_path = args[i].Replace("\"", @"\"); 

Tuy nhiên, tôi chắc chắn có một thực hành tốt nhất cho việc này. Làm thế nào có thể một cách chính xác phân tích cú pháp một dòng lệnh mà inlcudes đường dẫn, ngăn chặn các args [] mảng từ không đúng cách được dân cư với stings đã được phân tích cú pháp cho các ký tự thoát?

LƯU Ý: Tôi không muốn bao gồm toàn bộ thư viện phân tích cú pháp dòng lệnh trong dự án của mình! Tôi chỉ cần xử lý các đường dẫn được trích dẫn và muốn làm như vậy theo kiểu "thủ công". Vui lòng không đề nghị NConsoler, Mono hoặc bất kỳ thư viện phân tích cú pháp dòng lệnh "bồn rửa nhà bếp" lớn nào khác.

CSONG LƯU Ý: Theo như tôi có thể biết, đây không phải là câu hỏi trùng lặp. Trong khi các câu hỏi khác tập trung vào phân tích cú pháp dòng lệnh chung, câu hỏi này là cụ thể cho vấn đề mà đường dẫn giới thiệu khi các phần của chúng được hiểu là chuỗi thoát.

+0

Trường hợp chính xác bạn thấy nhân vật phụ này? Tôi đang sử dụng trình biên dịch đoạn mã. Đây là chuỗi chính .. string s = args [0]; \t \t Console.WriteLine (s); Và nó hoạt động như nó cần. – shahkalpesh

+0

@shahkalpesh: Dunno về trình biên dịch đoạn mã của bạn, nhưng hãy thử chạy nó từ dòng lệnh và cung cấp chương trình của bạn với đối số kết thúc bằng \ "(dấu gạch chéo ngược-doublequote). Như ebwi đã nói, mở mắt ra. –

+0

Tôi hiểu ngay bây giờ. Xin lỗi rằng tôi không hiểu chính xác đối số đầu vào – shahkalpesh

Trả lời

8

Không phải là câu trả lời, nhưng đây là một số background and explanation từ Jeffrey Tân, Microsoft hỗ trợ cộng đồng trực tuyến (2006/12/07):

Lưu ý: đây không phải là không một mã thất bại nhưng do thiết kế, vì backslashe là thường được sử dụng để thoát khỏi ký tự đặc biệt nhất định. Ngoài ra, thuật toán này giống với lệnh Win32 đối số dòng phân tích hàm CommandLineToArgvW. Xem chú thích phần dưới đây: http://msdn2.microsoft.com/en-us/library/bb776391.aspx

Cũng làm tham chiếu đến phương pháp FX Environment.GetCommandLineArgs cho giải thích thêm về hành vi xử lý dấu gạch chéo.

Cá nhân tôi nghĩ đây là một sự lôi kéo, và tôi ngạc nhiên là trước đây tôi chưa từng chút nào. Hoặc có lẽ tôi có và không biết điều đó? Thay thế mù của dấu ngoặc kép với dấu gạch chéo không tấn công tôi như là một giải pháp, mặc dù. Tôi đang bỏ phiếu cho câu hỏi, bởi vì nó là một cái mở mắt.

1

Tôi thích ý tưởng của bạn:

_path = args[i].Replace("\"", @"\"); 

Nó là sạch, và sẽ không có hiệu lực trừ khi vấn đề tồn tại.

+0

Nhưng điều này sẽ không hoạt động nếu bạn có: example.exe một "C: \ InputFolder \" "C: \ OutuptFolder \" như hai đường dẫn sẽ được concatinated như arg [1] = C: \ InputFolder "C: \ Outpurfolder" –

1

Tôi đã có cùng một sự thất vọng.Giải pháp của tôi là sử dụng cụm từ thông dụng. Đầu vào dự kiến ​​của tôi là một danh sách các đường dẫn, một số trong đó có thể được trích dẫn. Các kludge trên không hoạt động trừ khi tất cả các đối số cuối cùng được trích dẫn.

// Capture quoted string or non-quoted strings followed by whitespace 
string exp = @"^(?:""([^""]*)""\s*|([^""\s]+)\s*)+"; 
Match m = Regex.Match(Environment.CommandLine, exp); 

// Expect three Groups 
// group[0] = entire match 
// group[1] = matches from left capturing group 
// group[2] = matches from right capturing group 
if (m.Groups.Count < 3) 
    throw new ArgumentException("A minimum of 2 arguments are required for this program"); 

// Sort the captures by their original postion 
var captures = m.Groups[1].Captures.Cast<Capture>().Concat(
       m.Groups[2].Captures.Cast<Capture>()). 
       OrderBy(x => x.Index). 
       ToArray(); 

// captures[0] is the executable file 
if (captures.Length < 3) 
    throw new ArgumentException("A minimum of 2 arguments are required for this program"); 

Mọi người có thể xem regex hiệu quả hơn không?

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