2009-05-22 12 views
21

Jak można analizować argumenty wiersza polecenia, które mają być interpretowane jako ścieżki? arg [], zawiera łańcuchy, które są automatycznie łączone, jeżeli są podane, na przykład:C# Analiza linii poleceń cytowanych ścieżek i unikanie znaków ucieczki

example.exe jeden dwa „trzy cztery”

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

Jednakże arg [] nie właściwość analizy składniowej „C: \ Przykład \ "jako argument. Zamiast tego, poda argument jako "C: \ Przykład" "(z dodatkowym cudzysłowem). Jest to spowodowane odwróconym ukośnikiem w ścieżce traktowanej jako znak escape, a tym samym końcowym cytatem, który użytkownik podał na komendzie -line staje się częścią argumentu

.eg.

example.exe jeden "C: \ InputFolder" "C: \ OutuptFolder \"

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

Łatwym kludge może być:

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

Jestem jednak pewien, że istnieje najlepsza praktyka. W jaki sposób można poprawnie parsować linię poleceń, która zawiera ścieżki, zapobiegając niewłaściwemu wypełnieniu tablicy args [] przez ukłucia, które zostały przetworzone na znaki ucieczki?

UWAGA: Nie chciałbym dołączyć do mojego projektu całej biblioteki parsowania linii poleceń! Potrzebuję tylko obsługi cytowanych ścieżek i chcę to zrobić w "ręczny" sposób. Proszę nie polecać NConsoler, Mono ani żadnej innej dużej biblioteki parsowania wiersza poleceń.

UWAGA: Z tego co wiem, nie jest to duplikat pytania. Podczas gdy inne pytania koncentrują się na ogólnym analizie linii komend, to pytanie jest specyficzne dla problemu, który ścieżki wprowadzają, gdy ich części są interpretowane jako sekwencje specjalne.

+0

Gdzie dokładnie widzisz tę dodatkową postać? Używam kompilatora fragmentów. Oto główny ciąg .. string s = args [0]; \t \t Console.WriteLine (s); I działa tak, jak powinien. – shahkalpesh

+0

@shahkalpesh: Dunno o kompilatorze kodu, ale spróbuj uruchomić go z wiersza poleceń, i podaj swój program argumentem kończącym się na \ "(backslash-doublequote) .Obowiązek ebwi, otworzył mi oczy –

+0

Dostaję to teraz. Przepraszam, że nie zrozumiałem poprawnie argumentu wejściowego – shahkalpesh

Odpowiedz

8

nie odpowiedź, ale oto niektóre background and explanation od Jeffrey Tan, Microsoft Online Community obsługa (07.12.2006):

Uwaga: nie jest to nie porażka kod ale przez projekt, ponieważ backslashe to zwykle używane do unikania określonych znaków specjalnych . Ponadto ten algorytm jest taki sam jak polecenie Win32 funkcja analizy argumentów wiersza CommandLineToArgvW. Patrz Uwagi sekcji poniżej: http://msdn2.microsoft.com/en-us/library/bb776391.aspx

sprawia także odniesienie do metody FX Environment.GetCommandLineArgs dla wyjaśnienia zachowania obsługi ukośnik.

Osobiście uważam, że jest to opór i jestem zaskoczony, że nie byłem w tym wcześniej. A może mam i nie wiem? Ślepe zastąpienie cudzysłowów ukośnikami nie wydaje mi się jednak rozwiązaniem. Głosuję na to pytanie, ponieważ był to otwieracz do oczu.

1

Lubię swój pomysł:

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

Jest czysty i będzie miał żadnego wpływu, chyba że problem istnieje.

+0

Ale to nie zadziała, jeśli masz: przykład.exe jeden "C: \ InputFolder \" "C: \ OutuptFolder \" jako że dwie ścieżki uzyskają konkatinację jako arg [1] = C: \ InputFolder "C: \ Outpurfolder" –

1

Miałem tę samą frustrację.Moim rozwiązaniem było użycie wyrażeń regularnych. Moje oczekiwane dane wejściowe to lista ścieżek, z których niektóre mogą być cytowane. Powyższy kludge nie działa, dopóki nie zostaną podane wszystkie ostatnie argumenty.

// 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"); 

Czy ktoś może zobaczyć bardziej efektywne wyrażenie regularne?

Powiązane problemy