Благодарение на @mp3ferret за правилната идея. Но нямаше пример за решение, използващо Environment.CommandLine
, така че продължих и създадох OriginalCommandLine
клас, който ще получи аргументите на командния ред, както са въведени първоначално.
Аргументът се дефинира в регулярния израз tokenizer
като низ в двойни кавички от всякакъв тип знак или низ без кавички от знаци без интервали. В рамките на низовете в кавички символът за кавички може да бъде екраниран с обратна наклонена черта. Въпреки това обратна наклонена черта в края, последвана от двойна кавичка и след това бяло пространство, няма да бъдат екранирани.
Причината, поради която избрах изключението за бягство поради празно пространство, беше да приспособя кавички, които завършват с обратна наклонена черта. Вярвам, че е много по-малко вероятно да се натъкнете на ситуация, в която всъщност бихте искали екранираните двойни кавички.
Код
static public class OriginalCommandLine
{
static Regex tokenizer = new Regex(@"""(?:\\""(?!\s)|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(@"\\("")(?!\s|$)");
static Regex unquoter = new Regex(@"^\s*""|""\s*$");
static Regex quoteTester = new Regex(@"^\s*""(?:\\""|[^""])*""\s*$");
static public string[] Parse(string commandLine = null)
{
return tokenizer.Matches(commandLine ?? Environment.CommandLine).Cast<Match>()
.Skip(1).Select(m => unescaper.Replace(m.Value, @"""")).ToArray();
}
static public string UnQuote(string text)
{
return (IsQuoted(text)) ? unquoter.Replace(text, "") : text;
}
static public bool IsQuoted(string text)
{
return text != null && quoteTester.Match(text).Success;
}
}
Резултати
Както можете да видите от резултатите по-долу, корекциите на горния метод поддържат кавичките, като същевременно се справят по-елегантно с реалистичен сценарий, който може да срещнете.
Test:
ConsoleApp1.exe foo1 notepad.exe "C:\Progra\"m Files\MyDocuments\" "C:\Program Files\bar.txt"
args[]:
[0]: foo1
[1]: notepad.exe
[2]: C:\Progra"m Files\MyDocuments" C:\Program
[3]: Files\bar.txt
CommandLine.Parse():
[0]: foo1
[1]: notepad.exe
[2]: "C:\Progra"m Files\MyDocuments\"
[3]: "C:\Program Files\bar.txt"
Накрая
Обсъждах използването на алтернативна схема за избягване на двойни кавички. Смятам, че използването на ""
е по-добро, като се има предвид, че командните редове толкова често се занимават с обратни наклонени черти. Запазих метода за екраниране на обратната наклонена черта, защото той е обратно съвместим с това как обикновено се обработват аргументите на командния ред.
Ако искате да използвате тази схема, направете следните промени в регулярните изрази:
static Regex tokenizer = new Regex(@"""(?:""""|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(@"""""");
static Regex unquoter = new Regex(@"^\s*""|""\s*$");
static Regex quoteTester = new Regex(@"^\s*""(?:""""|[^""])*""\s*$");
Ако искате да се доближите до това, което очаквате от args
, но с непокътнати кавички, променете двата регулярни израза. Все още има малка разлика, "abc"d
ще върне abcd
от args
, но [0] = "abc", [1] = d
от моето решение.
static Regex tokenizer = new Regex(@"""(?:\\""|[^""])*""|[^\s]+");
static Regex unescaper = new Regex(@"\\("")");
Ако наистина, наистина искате да получите същия брой елементи като args
, използвайте следното:
static Regex tokenizer = new Regex(@"(?:[^\s""]*""(?:\\""|[^""])*"")+|[^\s]+");
static Regex unescaper = new Regex(@"\\("")");
Резултат от точно съвпадение
Test: "zzz"zz"Zzz" asdasd zz"zzz" "zzz"
args OriginalCommandLine
------------- -------------------
[0]: zzzzzZzz [0]: "zzz"zz"Zzz"
[1]: asdasd [1]: asdasd
[2]: zzzzz [2]: zz"zzz"
[3]: zzz [3]: "zzz"
person
Daniel Gimenez
schedule
05.09.2013
MyApp.exe foo1 "notepad.exe \"C:\Program Files\readme.txt\" "
? Ще трябва да видите как можете да кодирате двойни кавички. - person Akash Kava   schedule 04.09.2013