Разбор аргументов командной строки с кавычками - PullRequest
0 голосов
/ 08 января 2020

Хорошо, поэтому я разбиваю аргументы командной строки пробелами, например, в командной строке, но проблема в том, что если пользователь пытается ввести в DoStuff «аргумент, в котором есть пробелы, но он заключен в кавычки», он не разделит его правильно. Я использую консольное приложение. Я пытался сделать это так: baseCommand - это строка, которую пользователь вводит в неразобранном виде, а secondCommand должен быть вторым аргументом.

int firstQuoteIndex = baseCommand.IndexOf('"');

if (firstQuoteIndex != -1)
{
    int secondQuoteIndex = baseCommand.LastIndexOf('"');
    secondCommand = baseCommand.Substring(firstQuoteIndex, 
        secondQuoteIndex - firstQuoteIndex + 1).Replace("\"", "");
}

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

DoSomething "second arg that has spaces" "third arg that has spaces"

Имейте в виду, что пользователю не нужно вводить кавычки, если аргумент (ы) нет кавычек. Кто-нибудь есть какие-либо предложения, спасибо.

Ответы [ 2 ]

0 голосов
/ 08 января 2020

Я уверен, что есть более элегантный способ сделать это, но один из них - просто пройти по командной строке по одному символу за раз, отслеживая, если вы «внутри строки в кавычках», и просто создать аргументы, как вы go, добавляя их в список, когда вы встречаете конечную кавычку или пробел, который не находится внутри строки в кавычках.

Например:

public static List<string> ParseCommandLine(string cmdLine)
{
    var args = new List<string>();
    if (string.IsNullOrWhiteSpace(cmdLine)) return args;

    var currentArg = new StringBuilder();
    bool inQuotedArg = false;

    for (int i = 0; i < cmdLine.Length; i++)
    {
        if (cmdLine[i] == '"')
        {
            if (inQuotedArg)
            {
                args.Add(currentArg.ToString());
                currentArg = new StringBuilder();
                inQuotedArg = false;
            }
            else
            {
                inQuotedArg = true;
            }
        }
        else if (cmdLine[i] == ' ')
        {
            if (inQuotedArg)
            {
                currentArg.Append(cmdLine[i]);
            }
            else if (currentArg.Length > 0)
            {
                args.Add(currentArg.ToString());
                currentArg = new StringBuilder();
            }
        }
        else
        {
            currentArg.Append(cmdLine[i]);
        }
    }

    if (currentArg.Length > 0) args.Add(currentArg.ToString());

    return args;
}

Использование может выглядеть как:

public static void Main()
{
    var args = "one two \"three four\" five \"six seven\" eight \"nine ten";

    Console.WriteLine($"Command line: \"{args}\"\n");
    Console.WriteLine("Individual Arguments");
    Console.WriteLine("--------------------");
    Console.WriteLine(string.Join(Environment.NewLine, ParseCommandLine(args)));

    GetKeyFromUser("\nDone! Press any key to exit...");
}

Выход

enter image description here

0 голосов
/ 08 января 2020

Вы можете использовать следующее регулярное выражение для этой цели.

[\""].+?[\""]|[^ ]+

Например,

var commandList = Regex.Matches(baseCommand, @"[\""].+?[\""]|[^ ]+")
                .Cast<Match>()
                .Select(x => x.Value.Trim('"'))
                .ToList();

Образец 1 Ввод

DoSomething "second arg that has spaces" thirdArgumentWithoutSpaces

Выход

Command List
------------
DoSomething 
second arg that has spaces
thirdArgumentWithoutSpaces

Образец 2 Вход

DoSomething "second arg that has spaces" "third Argument With Spaces"

Выход

Command List
------------
DoSomething 
second arg that has spaces
third Argument With Spaces
...