Najlepszy sposób na analizę argumentów wiersza poleceń w C#? [zamknięte]

Podczas budowania aplikacji konsolowych, które przyjmują parametry, można użyć argumentów przekazanych do Main(string[] args).

W przeszłości po prostu indeksowałem / zapętlałem tę tablicę i zrobiłem kilka wyrażeń regularnych, aby wyodrębnić wartości. Jednak, gdy polecenia stają się bardziej skomplikowane, parsowanie może być dość brzydkie.

Więc jestem zainteresowany:

  • Biblioteki, których używasz
  • Wzory, których używasz

Załóżmy, że polecenia zawsze są zgodne ze wspólnymi standardami, takimi jak odpowiedział tutaj .

Author: Community, 2009-01-29

20 answers

Zdecydowanie sugerowałbym użycie NDesk.Opcje (Dokumentacja ) i / lub Mono.Options (to samo API, Inna Przestrzeń nazw). Przykład z dokumentacji :

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;
}
 324
Author: jonp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 05:03:20

Bardzo podoba mi się biblioteka parsera linii poleceń ( http://commandline.codeplex.com / ). Posiada bardzo prosty i elegancki sposób ustawiania parametrów za pomocą atrybutów:

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();
    }
}
 198
Author: Adrian Grigore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-17 01:57:33

WPF TestApi library zawiera jeden z najładniejszych parserów wiersza poleceń do programowania w C#. Bardzo polecam zajrzeć do niego z bloga Ivo Manolova na 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);
 50
Author: user7116,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-30 00:40:57
 24
Author: abatishchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-29 11:16:05

Wygląda na to, że każdy ma swoje własne parsery wiersza poleceń, pomyślałem, że ja też dodam swoje:).

Http://bizark.codeplex.com/

Ta biblioteka zawiera parser wiersza poleceń, który zainicjalizuje klasę z wartościami z wiersza poleceń. Ma mnóstwo funkcji (buduję go przez wiele lat).

Z dokumentacji ...

Parsowanie wiersza poleceń w frameworku BizArk ma ten klucz cechy:

  • Automatyczna inicjalizacja: właściwości klasy są automatycznie ustawiane na podstawie argumentów linii poleceń.
  • domyślne właściwości: wysyłanie wartości bez podawania nazwy właściwości.
  • Konwersja wartości: używa potężnej klasy ConvertEx zawartej również w BizArk do konwersji wartości na odpowiedni typ.
  • flagi logiczne: flagi mogą być określone po prostu za pomocą argumentu (ex, / b Dla true I / b- dla false) lub przez dodanie wartości true / false, yes / no, itd.
  • Tablice argumentów: Po prostu dodaj wiele wartości po nazwie wiersza poleceń, aby ustawić właściwość zdefiniowaną jako tablica. Ex, / x 1 2 3 wypełni x tablicą { 1, 2, 3 } (zakładając, że X jest zdefiniowana jako tablica liczb całkowitych).
  • aliasy linii poleceń: właściwość może obsługiwać dla niej wiele aliasów linii poleceń. Na przykład pomoc używa aliasu ?.
  • Nazwa częściowa rozpoznawanie: nie musisz pisać pełnej nazwy lub aliasu, wystarczy przeliterować na tyle, aby parser rozdzielił właściwość/alias od innych.
  • obsługuje ClickOnce: może inicjalizować właściwości, nawet jeśli są one określone jako ciąg zapytania w adresie URL dla wdrożonych aplikacji ClickOnce. Metoda inicjalizacji wiersza poleceń wykryje, czy jest uruchomiona jako ClickOnce, czy nie, więc Twój kod nie musi się zmieniać podczas korzystania z niego.
  • automatycznie tworzy /? help: obejmuje to ładne formatowanie, które uwzględnia szerokość konsoli.
  • załaduj / Zapisz argumenty wiersza poleceń do pliku: {[19] } jest to szczególnie przydatne, jeśli masz wiele dużych, złożonych zestawów argumentów wiersza poleceń, które chcesz uruchomić wiele razy.
 14
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-01 01:03:02

Jakiś czas temu napisałem parser argumentów linii poleceń C#. Its at: http://www.codeplex.com/CommandLineArguments

 13
Author: PeterH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-15 07:07:43

CLAP (Parser argumentów linii poleceń) ma użyteczny API i jest wspaniale udokumentowany. Tworzysz metodę, opisując parametry. https://github.com/adrianaisemberg/CLAP

 9
Author: Colonel Panic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 12:50:52

Istnieje wiele rozwiązań tego problemu. Dla kompletności i zapewnienia alternatywy, jeśli ktoś chce, dodaję tę odpowiedź dla dwóch przydatnych klas w mojej Google code library .

Pierwsza to ArgumentList, która odpowiada tylko za parsowanie parametrów wiersza poleceń. Zbiera pary nazwa-wartość zdefiniowane przez przełączniki "/ x:y " lub "- X=y", a także zbiera listę pozycji "nienazwanych". Tutaj omówiono podstawowe użycie , Zobacz klasę tutaj .

Drugą częścią tego jest Command-Interpreter, który tworzy w pełni funkcjonalną aplikację wiersza poleceń z twojej klasy.Net. Jako przykład:

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)
        { ... }

Z powyższym przykładowym kodem można uruchomić:

Program.exe DoSomething "string value" 5

-- lub --

Program.exe dosomething / ivalue=5-svalue: "string value"

To jest tak proste, jak to lub tak złożone, jak tego potrzebujesz. Możesz przejrzeć kod źródłowy, wyświetl pomoc lub pobierz plik binarny.
 5
Author: csharptest.net,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-04 15:53:52

Lubię Ten, ponieważ można "zdefiniować reguły" dla argumentów, potrzebnych lub nie,...

Lub jeśli jesteś facetem Uniksa, niż może Ci się spodobać GNU Getopt.NET port.

 4
Author: Xn0vv3r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-29 13:43:09

Mój dywan może Ci się spodobać.Cmd

Łatwy w użyciu i rozszerzalny parser argumentów wiersza poleceń. Uchwyty: Bool, Plus / Minus, String, String List, CSV, Enumeration.

Wbudowany '/? tryb pomocy.

Wbudowany '/??"i"/?D ' tryb generatora dokumentów.

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: to jest mój projekt i jako taka odpowiedź nie powinna być postrzegana jako poparcie strony trzeciej. To powiedziawszy, używam go dla każdego programu opartego na wierszu poleceń, który piszę, jest open source i to mam nadzieję, że inni mogą z tego skorzystać.

 4
Author: Phill Tew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-23 19:22:16

Istnieje parser argumentów linii poleceń w http://www.codeplex.com/commonlibrarynet

Może analizować argumenty za pomocą
1. atrybuty
2. explicit calls
3. pojedyncza linia wielu argumentów lub tablica łańcuchów

Może obsługiwać takie rzeczy jak:

-config : Qa -startdate:${dzisiaj} -region :' New York ' Settings01

Jest bardzo łatwy w użyciu.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 21:28:20

To jest handler, który napisałem na podstawie klasy Novell Options.

Ten jest przeznaczony dla aplikacji konsolowych, które wykonują pętlę stylu while (input !="exit"), interaktywną konsolę, na przykład konsolę FTP.

Przykładowe użycie:

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();
    }
}

I źródło:

/// <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;
    }
}
 2
Author: Chris S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-21 10:59:21

Moim ulubionym jest http://www.codeproject.com/KB/recipes/plossum_commandline.aspx Autor: Piotr Palotas:

[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;
}
 2
Author: Raphael Bossek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-12 06:08:45

Ostatnio natknąłem się na implementację parsowania wiersza poleceń FubuCore bardzo mi się podoba, powody są następujące:

  • jest łatwy w użyciu - chociaż nie mogłem znaleźć dla niego dokumentacji, rozwiązanie FubuCore zapewnia również projekt zawierający ładny zestaw testów jednostkowych, które mówią więcej o funkcjonalności niż jakakolwiek dokumentacja]}
  • ma ładny obiektowy projekt, brak powtórzeń kodu lub innych tego typu rzeczy, które miałem kiedyś w moim parsowaniu wiersza poleceń aplikacje
  • to deklaratywne: w zasadzie piszesz klasy dla poleceń i zestawów parametrów i dekorujesz je atrybutami, aby ustawić różne opcje (np. nazwa, opis, obowiązkowe/opcjonalne)
  • Biblioteka drukuje nawet ładny wykres użycia, oparty na tych definicjach

Poniżej znajduje się prosty przykład, jak tego użyć. Aby zilustrować użycie, napisałem proste narzędzie, które ma dwa polecenia: - add (dodaje obiekt do listy - obiekt składa się z name( string), value (int) i flaga logiczna) - list (wyświetla wszystkie aktualnie dodane obiekty)

Przede wszystkim napisałem klasę poleceń dla polecenia '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;
    }
}

To polecenie przyjmuje instancję CommandInput jako parametr, więc definiuję, że dalej:

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; }
}

Kolejnym poleceniem jest 'list', które jest zaimplementowane w następujący sposób:

[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;
    }
}

Polecenie 'list' nie pobiera żadnych parametrów, więc zdefiniowałem dla tego klasę NullInput:

public class NullInput { }

Wszystko, co teraz pozostało, to podłączyć to w metodzie Main (), tak:

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

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

Program działa zgodnie z oczekiwaniami, drukuje wskazówki dotyczące prawidłowego użycia w przypadku, gdy jakiekolwiek polecenia są nieprawidłowe:

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

Oraz przykładowe użycie polecenia "Dodaj":

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
  -------------------------------------
 2
Author: GolfWolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-11 06:50:37

Polecenia Powershell.

Parsowanie wykonywane przez powershell w oparciu o atrybuty określone w poleceniach, wsparcie dla walidacji, zestawów parametrów, pipelining, raportowanie błędów, pomoc, a co najlepsze zwracanie obiektów.NET do użycia w innych poleceniach.

Kilka linków, które uznałem za pomocne w rozpoczęciu pracy:

 2
Author: hannasm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-07 05:07:43

C# CLI jest bardzo prostą biblioteką parsującą argumenty linii poleceń, którą napisałem. Jest dobrze udokumentowany i open source.

 2
Author: Bernard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-11 15:02:34

Parser linii poleceń Genghis może być trochę nieaktualny, ale jest bardzo funkcjonalny i działa całkiem dobrze dla mnie.

 1
Author: devdimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-21 11:07:24

Proponuję bibliotekę open-source CSharpOptParse . Parsuje wiersz poleceń i nawadnia zdefiniowany przez użytkownika obiekt. NET z wejściem wiersza poleceń. Do tej biblioteki zawsze zwracam się pisząc aplikację konsolową C#.

 0
Author: Stuart Lange,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-23 14:09:11

Proszę użyć portu. NET API Apache commons CLI. To działa świetnie.

Http://sourceforge.net/projects/dotnetcli/

Oraz oryginalne API dla koncepcji i wprowadzenia

Http://commons.apache.org/cli/

 0
Author: Andreas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 09:04:55

Bardzo prosta, łatwa w użyciu Klasa ad hoc do parsowania wiersza poleceń, która obsługuje domyślne argumenty.

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"));
    }
}
 0
Author: Martin Lütken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-29 12:43:58