Beim Erstellen von Konsolenanwendungen, die Parameter verwenden, können Sie die an Main(string[] args)
übergebenen Argumente verwenden.
In der Vergangenheit habe ich dieses Array einfach indexiert/geloopt und ein paar reguläre Ausdrücke erstellt, um die Werte zu extrahieren. Wenn die Befehle jedoch komplizierter werden, kann das Parsen ziemlich hässlich werden.
Ich interessiere mich also für:
Angenommen, die Befehle halten sich immer an gängige Standards wie hier beantwortet .
Ich würde dringend empfehlen, NDesk.Options ( Documentation ) und/oder Mono.Options (gleiche API, unterschiedlicher Namespace) zu verwenden. Ein Beispiel aus der Dokumentation :
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;
}
Ich mag die Command Line Parser Library ( http://commandline.codeplex.com/ ). Es hat eine sehr einfache und elegante Art, Parameter über Attribute einzurichten:
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();
}
}
Die WPF-TestApi-Bibliothek enthält einen der schönsten Befehlszeilenparser für die C # -Entwicklung. Ich empfehle dringend, sich das anzuschauen, von Ivo Manolovs Blog auf der 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);
Schauen Sie sich http://github.com/mono/mono/tree/master/mcs/class/Mono.Options/ an
Es sieht so aus, als ob jeder seine eigenen Kommandozeilen-Parser hat, ich sollte auch meine hinzufügen :).
Diese Bibliothek enthält einen Kommandozeilen-Parser , der eine Klasse mit den Werten aus der Kommandozeile initialisiert. Es hat eine Menge Funktionen (ich habe es über viele Jahre aufgebaut).
Aus der Dokumentation ...
Die Befehlszeilenanalyse im BizArk-Framework weist die folgenden Hauptfunktionen auf:
Ich habe vor einiger Zeit einen C # -Befehlszeilen-Parser geschrieben. Sein an: http://www.codeplex.com/CommandLineArguments
CLAP (Kommandozeilenargument-Parser) hat eine verwendbare API und ist wunderbar dokumentiert. Sie erstellen eine Methode, in der Sie die Parameter mit Anmerkungen versehen. https://github.com/adrianaisemberg/CLAP
Es gibt zahlreiche Lösungen für dieses Problem. Der Vollständigkeit halber und um auf Wunsch eine Alternative anzubieten, füge ich diese Antwort für zwei nützliche Klassen in meine Google Code Library ein.
Das erste ist ArgumentList, das nur für das Parsen von Befehlszeilenparametern zuständig ist. Es sammelt Name-Wert-Paare, die durch die Schalter '/ x: y' oder '-x = y' definiert sind, und sammelt auch eine Liste von 'unbenannten' Einträgen. Es ist grundlegend die Verwendung wird hier besprochen , die Klasse hier ansehen .
Der zweite Teil davon ist der CommandInterpreter , der aus Ihrer .Net-Klasse eine voll funktionsfähige Befehlszeilenanwendung erstellt. Als Beispiel:
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)
{ ... }
Mit dem obigen Beispielcode können Sie Folgendes ausführen:
Program.exe DoSomething "Zeichenfolgenwert" 5
-- oder --
Program.exe dosomething/ivalue = 5 -svalue: "string value"
So einfach oder so komplex, wie Sie es brauchen. Sie können den Quellcode überprüfen , die Hilfe anzeigen oder die Binärdatei herunterladen .
Sie können mein mögen Rug.Cmd
Einfach zu verwendender und erweiterbarer Parser für Befehlszeilenargumente. Handles: Bool, Plus/Minus, String, String-Liste, CSV, Aufzählung.
Eingebaut in '/?' Hilfemodus.
Baujahr '/ ??' und '/? D' Dokumentgenerator-Modi.
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);
}
}
}
Bearbeiten: Dies ist mein Projekt und als solche sollte diese Antwort nicht als Befürwortung von Dritten gesehen werden. Das heißt, ich verwende es für jedes Kommandozeilenprogramm, das ich schreibe. Es ist Open Source und ich hoffe, dass andere davon profitieren können.
Ich mag dieses , weil Sie "Regeln definieren" können für die Argumente, die benötigt werden oder nicht, ...
oder wenn Sie ein Unix-Typ sind, dann könnte Ihnen der GNU Getopt .NET -Port gefallen.
Es gibt einen Parser für Befehlszeilenargumente unter http://www.codeplex.com/commonlibrarynet
Es kann Argumente mit analysieren
1. Attribute
2. explizite Anrufe
3. einzelne Zeile mit mehreren Argumenten OR Zeichenfolgenarray
Es kann mit Dingen wie den folgenden umgehen:
- config : Qa - startdate : $ { Heute } - Region : 'New York' Einstellungen01
Es ist sehr einfach zu bedienen.
Dies ist ein Handler, den ich basierend auf der Klasse Novell Options
geschrieben habe.
Diese richtet sich an Konsolenanwendungen, die eine while (input !="exit")
-Stilschleife ausführen, z. B. eine interaktive Konsole wie eine FTP-Konsole.
Anwendungsbeispiel:
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();
}
}
Und die Quelle:
/// <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;
}
}
Ich bin kürzlich auf die FubuCore-Kommandozeilen-Parsing-Implementierung gestoßen. Die Gründe dafür sind:
Nachfolgend finden Sie ein einfaches Beispiel zur Verwendung. Um die Verwendung zu veranschaulichen, habe ich ein einfaches Hilfsprogramm geschrieben, das zwei Befehle enthält: - add (fügt ein Objekt zu einer Liste hinzu - ein Objekt besteht aus einem Namen (String), einem Wert (int) und einem Booleschen Flag) - list (lists alle aktuell hinzugefügten Objekte)
Zunächst habe ich eine Command-Klasse für den Befehl 'add' geschrieben:
[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;
}
}
Dieser Befehl verwendet eine CommandInput-Instanz als Parameter, daher definiere ich Folgendes:
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; }
}
Der nächste Befehl ist 'list', der wie folgt implementiert wird:
[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;
}
}
Der Befehl 'list' akzeptiert keine Parameter, daher habe ich eine NullInput-Klasse definiert:
public class NullInput { }
Jetzt müssen Sie dies nur noch in der Main () -Methode verkabeln:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
Das Programm funktioniert wie erwartet und gibt Hinweise zur korrekten Verwendung aus, falls Befehle ungültig sind:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
Und ein Anwendungsbeispiel für den Befehl 'add':
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 Commandlets.
Analyse durch Powershell basierend auf den in den Commandlets angegebenen Attributen, Unterstützung für Validierungen, Parametersätze, Pipelining, Fehlerberichterstattung, Hilfe und am besten Rückgabe von .NET-Objekten zur Verwendung in anderen Commandlets.
Ein paar Links, die ich hilfreich fand, als ich anfing:
Mein persönlicher Favorit ist http://www.codeproject.com/KB/recipes/plossum_commandline.aspx von Peter 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;
}
C # CLI ist eine sehr einfache Parsing-Bibliothek für Befehlszeilenargumente, die ich geschrieben habe. Es ist gut dokumentiert und Open Source.
Dschingis Kommandozeilen-Parser ist zwar etwas veraltet, aber das Feature ist sehr vollständig und funktioniert für mich ziemlich gut.
Ich würde die Open-Source-Bibliothek vorschlagen CSharpOptParse . Es analysiert die Befehlszeile und hydratisiert ein benutzerdefiniertes .NET-Objekt mit der Befehlszeileneingabe. Ich greife beim Schreiben einer C # -Konsolenanwendung immer auf diese Bibliothek zurück.
Bitte benutzen Sie den .net Port der Apache Commons Cli API. Das funktioniert super.
http://sourceforge.net/projects/dotnetcli/
und die ursprüngliche API für Konzepte und Einführung
Eine sehr einfache, benutzerfreundliche Ad-hoc-Klasse zum Parsen der Befehlszeile, die Standardargumente unterstützt.
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"));
}
}