2013-06-11 4 views
4

Я хотел бы разделить строку, используя пробел, как мой разделитель, но если есть несколько слов, заключенных в двойные или одинарные кавычки, то я бы хотел, чтобы они были возвращены как один элемент.Функция RegEx для синтаксического анализа командной строки без использования библиотеки

Например, если входная строка:

CALL "C:\My File Name With Space" /P1 P1Value /P1 P2Value

Результирующий массив будет:

Array[0]=Call 
Array[1]=C:\My File Name With Space 
Array[2]=/P1 
Array[3]=P1Value 
Array[4]=/P1 
Array[5]=P2Value 

Как использовать регулярные выражения, чтобы сделать это? Я понимаю, что есть синтаксические анализаторы командной строки. Я бегло взглянул на популярный, но не справился с ситуацией, когда у вас может быть несколько параметров с тем же именем. В любом случае вместо обучения использованию библиотеки синтаксического анализа командной строки (оставьте это на другой день). Мне интересно узнать больше о функциях RegEx.

Как бы вы использовали функцию RegEx для ее синтаксического анализа?

+1

Не так ли, что вам заданы аргументы командной строки в виде массива строк в Main()? –

+0

Нет, я разбираю пакетные файлы в папке. – ChadD

+1

Я бы не использовал регулярное выражение для обработки этого. В командных строках слишком много особых случаев. Вам лучше использовать одну из рекомендаций из http://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c?rq=1 или просто написать свой (что, возможно, займет пару часов). –

ответ

10

link в комментарии Джима Мишеля указывает, что Win32 API предоставляет функцию для этого. Я бы рекомендовал использовать это для согласованности. Вот пример (от PInvoke).

static string[] SplitArgs(string unsplitArgumentLine) 
{ 
    int numberOfArgs; 
    IntPtr ptrToSplitArgs; 
    string[] splitArgs; 

    ptrToSplitArgs = CommandLineToArgvW(unsplitArgumentLine, out numberOfArgs); 
    if (ptrToSplitArgs == IntPtr.Zero) 
     throw new ArgumentException("Unable to split argument.", 
      new Win32Exception()); 
    try 
    { 
     splitArgs = new string[numberOfArgs]; 
     for (int i = 0; i < numberOfArgs; i++) 
      splitArgs[i] = Marshal.PtrToStringUni(
       Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); 
     return splitArgs; 
    } 
    finally 
    { 
     LocalFree(ptrToSplitArgs); 
    } 
} 

[DllImport("shell32.dll", SetLastError = true)] 
static extern IntPtr CommandLineToArgvW(
    [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, 
    out int pNumArgs); 

[DllImport("kernel32.dll")] 
static extern IntPtr LocalFree(IntPtr hMem); 

Если вы хотите быстро и грязное, негибкое, хрупкое решение регулярного выражений вы можете сделать что-то вроде этого:

var rex = new Regex(@"("".*?""|[^ ""]+)+"); 
string test = "CALL \"C:\\My File Name With Space\" /P1 P1Value /P1 P2Value"; 
var array = rex.Matches(test).OfType<Match>().Select(m => m.Groups[0]).ToArray(); 
+0

Работал как шарм. Я удивлен, увидев, что код выходит за рамки рамки. Я чувствую себя немного грязным, не уверен, почему, возможно, потому что я не понимаю. – ChadD

+0

sqlcmd.exe (http://msdn.microsoft.com/en-us/library/ms162773.aspx), и, возможно, другие exes разрешают переключателям params в форме тире, за которыми следует одна буква, чтобы иметь ДОПОЛНИТЕЛЬНОЕ пространство перед записывая значение параметра. Например, «sqlcmd.exe -sMyServer» и «sqlcmd.exe -s MyServer» указывают одно и то же переданное значение. Однако эта функция передает 2 аргумента для первого и 3 для второго. – ChadD

+0

@ChadD - 'CommandLineToArgvW' - это то, что оболочка использует, чтобы выяснить, как передавать аргументы. sqlcmd.exe затем содержит логику, которая их интерпретирует. '-s MyServer' передается как два аргумента, но sqlcmd.exe распознает их как один из параметров вместе. – Chad

1

Я бы не сделать это с Regex, по разным причинам были показаны выше ,

Если я должен, это будет соответствовать вашим простым требованиям:

(".*?")|([^ ]+) 

Однако это не включает в себя:

  • кавычки экранированы
  • одинарные кавычки
  • не- ascii цитаты (вы не думаете, что люди будут вставлять умные цитаты из слова в ваш файл?)
  • сочетание с вышеизложенного

И это только у меня на голове.

1

@chad Henderson вы забыли включить одиночные кавычки, и это также имеет проблему захвата всего, что приходит перед набором кавычек.

вот исправление, включающее одинарные кавычки, но также показывает проблему с дополнительным захватом перед цитатой. http://regexhero.net/tester/?id=81cebbb2-5548-4973-be19-b508f14c3348

+0

Windows фактически не рассматривает одиночные кавычки так же, как и двойные кавычки. И вы не уверены, что типы котировок матч в вашем регулярном выражении :). Просто для удовольствия я обновил мой, чтобы поддерживать аргументы формы 'a 'bc" d' – Chad

+0

Мне любопытно, как обращаются окна с одинарными кавычками? –

+0

Windows лечит ' 'a b' 'как два отдельных аргумента,' 'a' и' b'' – Chad

Смежные вопросы