Лучший способ проанализировать аргументы командной строки в C#? [закрытый]

при создании консольных приложений, принимающих параметры, можно использовать аргументы, переданные в Main(string[] args).

в прошлом я просто индексировал / зацикливал этот массив и сделал несколько регулярных выражений для извлечения значений. Однако, когда команды усложняются, синтаксический анализ может стать довольно уродливым.

поэтому меня интересует:

  • библиотеки, которые вы используете
  • шаблоны, которые вы используете

предположим команды всегда придерживайтесь общих стандартов, таких как ответ тут.

20 ответов


Я настоятельно рекомендую использовать NDesk.Опции (документация) и/или моно.Опции (тот же API, другое пространство имен). Ан пример из документации:

bool show_help = false;
List<string> names = new List<string> ();
int repeat = 1;

var p = new OptionSet () {
    { "n|name=", "the {NAME} of someone to greet.",
       v => names.Add (v) },
    { "r|repeat=", 
       "the number of {TIMES} to repeat the greeting.\n" + 
          "this must be an integer.",
        (int v) => repeat = v },
    { "v", "increase debug message verbosity",
       v => { if (v != null) ++verbosity; } },
    { "h|help",  "show this message and exit", 
       v => show_help = v != null },
};

List<string> extra;
try {
    extra = p.Parse (args);
}
catch (OptionException e) {
    Console.Write ("greet: ");
    Console.WriteLine (e.Message);
    Console.WriteLine ("Try `greet --help' for more information.");
    return;
}

Мне очень нравится команда библиотеки парсер строки ( http://commandline.codeplex.com/ ). Он имеет очень простой и элегантный способ настройки параметров с помощью атрибутов:

class Options
{
    [Option("i", "input", Required = true, HelpText = "Input file to read.")]
    public string InputFile { get; set; }

    [Option(null, "length", HelpText = "The maximum number of bytes to process.")]
    public int MaximumLenght { get; set; }

    [Option("v", null, HelpText = "Print details during execution.")]
    public bool Verbose { get; set; }

    [HelpOption(HelpText = "Display this help screen.")]
    public string GetUsage()
    {
        var usage = new StringBuilder();
        usage.AppendLine("Quickstart Application 1.0");
        usage.AppendLine("Read user manual for usage instructions...");
        return usage.ToString();
    }
}

на библиотека WPF TestApi поставляется с одним из самых красивых парсеров командной строки для разработки C#. Я настоятельно рекомендую изучить его, от блог Иво Манолова на API:

// EXAMPLE #2:
// Sample for parsing the following command-line:
// Test.exe /verbose /runId=10
// This sample declares a class in which the strongly-
// typed arguments are populated
public class CommandLineArguments
{
   bool? Verbose { get; set; }
   int? RunId { get; set; }
}

CommandLineArguments a = new CommandLineArguments();
CommandLineParser.ParseArguments(args, a);


похоже, у всех есть свои собственные Парсеры командной строки, думаю, мне лучше добавить свой:).

http://bizark.codeplex.com/

эта библиотека содержит парсер командной строки это инициализирует класс со значениями из командной строки. Он имеет массу функций (я строил его на протяжении многих лет).

с документация...

парсинг в BizArk база имеет следующие ключевые особенности:
  • автоматическая инициализация: свойства класса автоматически устанавливаются на основе аргументов командной строки.
  • свойства по умолчанию: отправить значение без указания имени свойства.
  • преобразование значения: использует мощный класс ConvertEx, также включенный в BizArk для преобразования значений в правильный тип.
  • булевых флагов: Флаги можно указать, просто используя аргумент (например, / b для true и / b - для false) или добавив значение true/false, yes/no и т. д.
  • аргумент массивы: просто добавьте несколько значений после имени командной строки, чтобы задать свойство, определенное как массив. Ex, /x 1 2 3 заполнит X массивом { 1, 2, 3 } (предполагая, что x определяется как массив целых чисел).
  • псевдонимы: свойство может поддерживать несколько псевдонимы командной строки. Например, использует псевдоним ?.
  • частичное признание: вам не нужно произносить полное имя или псевдоним, достаточно просто произнести достаточно для синтаксического анализатора, чтобы устранить неоднозначность свойства/псевдонима от других.
  • Поддержка ClickOnce: можно инициализировать свойства, даже если они указаны в качестве строки запроса в URL-адресе для развернутых приложений ClickOnce. Метод инициализации командной строки определяет, он работает как ClickOnce или нет, поэтому ваш код не нужно изменять при его использовании.
  • автоматически создает /? помогите!--19--> это включает в себя хорошее форматирование, которое учитывает ширину консоли.
  • загрузить / сохранить аргументы командной строки в файл: это особенно полезно, если у вас есть несколько больших и сложных наборов аргументов командной строки, которые вы хотите запустить несколько раз.

некоторое время назад я написал парсер аргументов командной строки C#. Его at:http://www.codeplex.com/CommandLineArguments


хлоп (синтаксический анализатор аргументов командной строки) имеет полезный API и прекрасно документирован. Вы делаете метод, аннотируя параметры. https://github.com/adrianaisemberg/CLAP


есть множество решений этой проблемы. Для полноты и предоставления альтернативы, если кто-то желает, я добавляю этот ответ для двух полезных классов в my библиотека кода google.

первый-ArgumentList, который отвечает только за разбор параметров командной строки. Он собирает пары имя-значение, определенные коммутаторами "/ x: y " или "- x=y", а также собирает список "неназванных" записей. Это основное использование обсуждается здесь, посмотреть здесь класс.

вторая часть это CommandInterpreter который создает полнофункциональное приложение командной строки из вашего класса .Net. В качестве примера:

using CSharpTest.Net.Commands;
static class Program
{
    static void Main(string[] args)
    {
        new CommandInterpreter(new Commands()).Run(args);
    }
    //example ‘Commands’ class:
    class Commands
    {
        public int SomeValue { get; set; }
        public void DoSomething(string svalue, int ivalue)
        { ... }

с приведенным выше примером кода Вы можете запустить следующее:

просмотреть исходный код, справка или скачать бинарные.

Мне нравится этого, потому что вы можете "определить правила" для Аргументов, нужны или нет...

или если вы парень Unix, чем вам может понравиться GNU Getopt .NET порт.


вам может понравиться мой половик.Cmd

простой в использовании и расширяемый парсер аргументов командной строки. Ручки: Bool, плюс / минус, строка, список строк, CSV, перечисление.

построен в '/?' режим справки.

построен в '/??'и '/?D ' режимы генератора документов.

static void Main(string[] args) 
{            
    // create the argument parser
    ArgumentParser parser = new ArgumentParser("ArgumentExample", "Example of argument parsing");

    // create the argument for a string
    StringArgument StringArg = new StringArgument("String", "Example string argument", "This argument demonstrates string arguments");

    // add the argument to the parser 
    parser.Add("/", "String", StringArg);

    // parse arguemnts
    parser.Parse(args);

    // did the parser detect a /? argument 
    if (parser.HelpMode == false) 
    {
        // was the string argument defined 
        if (StringArg.Defined == true)
        {
            // write its value
            RC.WriteLine("String argument was defined");
            RC.WriteLine(StringArg.Value);
        }
    }
}

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


есть парсер аргументов командной строки вhttp://www.codeplex.com/commonlibrarynet

Он может анализировать аргументы с помощью
1. атрибуты
2. явные вызовы
3. одна строка из нескольких аргументов или string array

Он может обрабатывать следующие вещи:

-config: Qa -параметр StartDate:${} -края:' New York ' Settings01

Это очень проста в использовании.


это обработчик, который я написал на основе Novell Options класса.

этот предназначен для консольных приложений, которые выполняют while (input !="exit") style loop, интерактивная консоль, например, FTP-консоль.

пример использования:

static void Main(string[] args)
{
    // Setup
    CommandHandler handler = new CommandHandler();
    CommandOptions options = new CommandOptions();

    // Add some commands. Use the v syntax for passing arguments
    options.Add("show", handler.Show)
        .Add("connect", v => handler.Connect(v))
        .Add("dir", handler.Dir);

    // Read lines
    System.Console.Write(">");
    string input = System.Console.ReadLine();

    while (input != "quit" && input != "exit")
    {
        if (input == "cls" || input == "clear")
        {
            System.Console.Clear();
        }
        else
        {
            if (!string.IsNullOrEmpty(input))
            {
                if (options.Parse(input))
                {
                    System.Console.WriteLine(handler.OutputMessage);
                }
                else
                {
                    System.Console.WriteLine("I didn't understand that command");
                }

            }

        }

        System.Console.Write(">");
        input = System.Console.ReadLine();
    }
}

и источник:

/// <summary>
/// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options).
/// </summary>
public class CommandOptions
{
    private Dictionary<string, Action<string[]>> _actions;
    private Dictionary<string, Action> _actionsNoParams;

    /// <summary>
    /// Initializes a new instance of the <see cref="CommandOptions"/> class.
    /// </summary>
    public CommandOptions()
    {
        _actions = new Dictionary<string, Action<string[]>>();
        _actionsNoParams = new Dictionary<string, Action>();
    }

    /// <summary>
    /// Adds a command option and an action to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action action)
    {
        _actionsNoParams.Add(name, action);
        return this;
    }

    /// <summary>
    /// Adds a command option and an action (with parameter) to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate that has one parameter - string[] args.</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action<string[]> action)
    {
        _actions.Add(name, action);
        return this;
    }

    /// <summary>
    /// Parses the text command and calls any actions associated with the command.
    /// </summary>
    /// <param name="command">The text command, e.g "show databases"</param>
    public bool Parse(string command)
    {
        if (command.IndexOf(" ") == -1)
        {
            // No params
            foreach (string key in _actionsNoParams.Keys)
            {
                if (command == key)
                {
                    _actionsNoParams[key].Invoke();
                    return true;
                }
            }
        }
        else
        {
            // Params
            foreach (string key in _actions.Keys)
            {
                if (command.StartsWith(key) && command.Length > key.Length)
                {

                    string options = command.Substring(key.Length);
                    options = options.Trim();
                    string[] parts = options.Split(' ');
                    _actions[key].Invoke(parts);
                    return true;
                }
            }
        }

        return false;
    }
}

мой личный фаворит -http://www.codeproject.com/KB/recipes/plossum_commandline.aspx Питер Палотас:

[CommandLineManager(ApplicationName="Hello World",
    Copyright="Copyright (c) Peter Palotas")]
class Options
{
   [CommandLineOption(Description="Displays this help text")]
   public bool Help = false;

   [CommandLineOption(Description = "Specifies the input file", MinOccurs=1)]
   public string Name
   {
      get { return mName; }
      set
      {
         if (String.IsNullOrEmpty(value))
            throw new InvalidOptionValueException(
                "The name must not be empty", false);
         mName = value;
      }
   }

   private string mName;
}

Я недавно наткнулся на реализацию синтаксического анализа командной строки Fubucore мне очень нравится, причины:

  • это простой в использовании-хотя я не смог найти документацию для него, решение FubuCore также предоставляет проект, содержащий хороший набор модульных тестов, которые говорят больше о функциональности, чем любая документация может
  • он имеет хороший объектно-ориентированный дизайн, без повторения кода или других подобных вещей, которые я использовал в своей команде линия разбора приложений
  • это декларативно: вы в основном пишете классы для команд и наборов параметров и украшаете их атрибутами для установки различных параметров (например, имя, описание, обязательный/необязательный)
  • библиотека даже печатает хороший график использования, основанный на этих определениях

Ниже приведен простой пример того, как это использовать. Чтобы проиллюстрировать использование, я написал простую утилиту, которая имеет две команды: - add (добавляет объект в список - объект состоит из имени (строки), значения (int) и логического флага) - перечень (список всех добавленных объектов)

прежде всего, я написал класс команды для команды "add":

[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
    public override bool Execute(CommandInput input)
    {
        State.Objects.Add(input); // add the new object to an in-memory collection

        return true;
    }
}

эта команда принимает экземпляр CommandInput в качестве параметра, поэтому я определяю следующее:

public class CommandInput
{
    [RequiredUsage("add"), Description("The name of the object to add")]
    public string ObjectName { get; set; }

    [ValidUsage("add")]
    [Description("The value of the object to add")]
    public int ObjectValue { get; set; }

    [Description("Multiply the value by -1")]
    [ValidUsage("add")]
    [FlagAlias("nv")]
    public bool NegateValueFlag { get; set; }
}

следующая команда - "list", которая реализована следующим образом:

[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
    public override bool Execute(NullInput input)
    {
        State.Objects.ForEach(Console.WriteLine);

        return false;
    }
}

команда "list" не принимает параметров, поэтому я определил класс NullInput для это:

public class NullInput { }

все, что осталось, это подключить это в методе Main (), например:

    static void Main(string[] args)
    {
        var factory = new CommandFactory();
        factory.RegisterCommands(typeof(Program).Assembly);

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

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

  ------------------------
    Available commands:
  ------------------------
     add -> Add object
    list -> List objects
  ------------------------

и пример использования команды "добавить":

Usages for 'add' (Add object)
  add <objectname> [-nv]

  -------------------------------------------------
    Arguments
  -------------------------------------------------
     objectname -> The name of the object to add
    objectvalue -> The value of the object to add
  -------------------------------------------------

  -------------------------------------
    Flags
  -------------------------------------
    [-nv] -> Multiply the value by -1
  -------------------------------------

Командлеты Powershell.

синтаксический анализ, выполняемый powershell на основе атрибутов, указанных в командлетах, поддержка проверок, наборов параметров, конвейеризации, отчетов об ошибках, справки и лучше всего возвращаемых объектов .NET для использования в других командлетах.

несколько ссылок, которые я нашел полезными для начала:


C# CLI-это очень простая библиотека синтаксического анализа аргументов командной строки, которую я написал. Это хорошо документировано и с открытым исходным кодом.


Парсер Командной Строки Чингиса может быть немного устарел, но это очень полная функция и работает довольно хорошо для меня.


Я бы предложил библиотеку с открытым исходным кодом CSharpOptParse. Он анализирует командную строку и увлажняет пользовательский объект .NET с помощью ввода командной строки. Я всегда обращаюсь к этой библиотеке при написании консольного приложения C#.


пожалуйста, используйте порт .net API CLI Apache commons. Это отлично работает.

http://sourceforge.net/projects/dotnetcli/

и оригинальный API для концепций и введения

http://commons.apache.org/cli/


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

class CommandLineArgs
{
    public static CommandLineArgs I
    {
        get
        {
            return m_instance;
        }
    }

    public  string argAsString( string argName )
    {
        if (m_args.ContainsKey(argName)) {
            return m_args[argName];
        }
        else return "";
    }

    public long argAsLong(string argName)
    {
        if (m_args.ContainsKey(argName))
        {
            return Convert.ToInt64(m_args[argName]);
        }
        else return 0;
    }

    public double argAsDouble(string argName)
    {
        if (m_args.ContainsKey(argName))
        {
            return Convert.ToDouble(m_args[argName]);
        }
        else return 0;
    }

    public void parseArgs(string[] args, string defaultArgs )
    {
        m_args = new Dictionary<string, string>();
        parseDefaults(defaultArgs );

        foreach (string arg in args)
        {
            string[] words = arg.Split('=');
            m_args[words[0]] = words[1];
        }
    }

    private void parseDefaults(string defaultArgs )
    {
        if ( defaultArgs == "" ) return;
        string[] args = defaultArgs.Split(';');

        foreach (string arg in args)
        {
            string[] words = arg.Split('=');
            m_args[words[0]] = words[1];
        }
    }

    private Dictionary<string, string> m_args = null;
    static readonly CommandLineArgs m_instance = new CommandLineArgs();
}

class Program
{
    static void Main(string[] args)
    {
        CommandLineArgs.I.parseArgs(args, "myStringArg=defaultVal;someLong=12");
        Console.WriteLine("Arg myStringArg  : '{0}' ", CommandLineArgs.I.argAsString("myStringArg"));
        Console.WriteLine("Arg someLong     : '{0}' ", CommandLineArgs.I.argAsLong("someLong"));
    }
}