При создании консольных приложений, которые принимают параметры, вы можете использовать аргументы, переданные в Main(string[] args)
.
В прошлом я просто проиндексировал/заципил этот массив и сделал несколько регулярных выражений для извлечения значений. Однако, когда команды становятся более сложными, синтаксический анализ может стать довольно уродливым.
Итак, меня интересует:
Предположим, что команды всегда придерживаются общих стандартов, таких как здесь..
Я бы настоятельно предложил использовать NDesk.Options (Документация) и/или Mono.Options (тот же 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;
}
Мне очень нравится библиотека Parser командной строки (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 поставляется с одним из лучших анализаторов командной строки для разработки С#. Я настоятельно рекомендую изучить его, блог Иво Манолова в 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);
Похоже, у всех есть свои собственные синтаксические анализаторы командной строки, и мне лучше добавить мои:).
Эта библиотека содержит синтаксический анализатор командной строки, который инициализирует класс со значениями из командной строки. У этого есть тонна особенностей (я строил это в течение многих лет).
Из документации...
Разбор командной строки в структуре BizArk имеет следующие ключевые особенности:
Я написал синтаксический анализатор строки командной строки С# a while. Его at: http://www.codeplex.com/CommandLineArguments
CLAP (синтаксический анализатор командной строки) имеет полезный API и прекрасно документирован. Вы делаете метод, аннотируя параметры. https://github.com/adrianaisemberg/CLAP
myapp myverb -argname argvalue
(должен иметь -argname
) или myapp -help
(обычно --help
).
Существует множество решений этой проблемы. Для полноты и предоставления альтернативы, если кто-то желает, я добавляю этот ответ для двух полезных классов в библиотеку кодов 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)
{ ... }
В приведенном выше примере кода вы можете запустить следующее:
Program.exe DoSomething "string value" 5
- или -
Program.exe dosomething/ivalue = 5 -svalue: "string value"
Это так просто или так сложно, как вам нужно. Вы можете просмотреть исходный код, просмотреть справку, или загрузить двоичный файл.
Вам может понравиться мой Rug.Cmd
Простой в использовании и расширяемый синтаксический анализатор командной строки. Ручки: Bool, Plus/Minus, String, String List, CSV, Enumeration.
Построено в '/?' режим справки.
Построено в '/??' и '/? 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);
}
}
}
Изменить: Это мой проект, и поэтому этот ответ не следует рассматривать как подтверждение от третьей стороны. Тем не менее, я использую его для каждой программы на основе командной строки, которую я пишу, это с открытым исходным кодом, и я надеюсь, что другие могут извлечь из этого выгоду.
Мне нравится тот, потому что вы можете "определять правила" для аргументов, необходимых или нет,...
или если вы парень Unix, вам может понравиться порт GNU Getopt.NET.
Существует парсер аргументов командной строки в http://www.codeplex.com/commonlibrarynet
Он может анализировать аргументы, используя
1. атрибуты
2. Явные вызовы
3. одиночная строка из нескольких аргументов ИЛИ массив строк
Он может обрабатывать такие вещи, как следующее:
- config: Qa - startdate: ${сегодня} - регион: настройки 'New York '01
Он очень прост в использовании.
С# CLI - очень простая библиотека анализа аргументов аргументов командной строки, которую я написал. Это хорошо документированный и открытый исходный код.
Readme.mkd
в папке « Documentation
»).
Командные команды Powershell.
Анализ, выполненный powershell на основе атрибутов, указанных в командах, поддержка валидаций, наборов параметров, конвейерная обработка, отчет об ошибках, помощь и лучший из всех возвращающих объектов .NET для использования в других командах.
Несколько ссылок, которые я нашел полезными при запуске:
Недавно я столкнулся с реализацией синтаксического анализа командной строки FubuCore. Мне это очень нравится, причины:
Ниже приведен простой пример того, как это использовать. Чтобы проиллюстрировать использование, я написал простую утилиту, которая имеет две команды: - добавить (добавляет объект в список - объект состоит из имени (строки), значения (int) и логического флага) - список (список всех добавленных объектов)
Прежде всего, я написал класс Command для команды '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; }
}
Следующая команда - это "список", которая реализована следующим образом:
[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
------------------------
И пример использования команды '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
-------------------------------------
Мой личный фаворит 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;
}
Это обработчик, который я написал на основе класса Novell Options
.
Этот файл предназначен для консольных приложений, которые выполняют цикл стиля while (input !="exit")
, например, интерактивную консоль, такую как консоль 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;
}
}
"Чангисская командная строка" Parser может быть немного устаревшим, но он очень функциональный и работает очень хорошо для меня.
Очень простой в использовании ad hoc класс для синтаксического анализа командной строки, который поддерживает аргументы по умолчанию.
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"));
}
}
Пожалуйста, используйте порт .net API apache commons cli. Это отлично работает.
http://sourceforge.net/projects/dotnetcli/
и оригинальный API для концепций и внедрения
Я бы предложил библиотеку с открытым исходным кодом CSharpOptParse. Он анализирует командную строку и увлажняет пользовательский объект .NET с помощью ввода командной строки. Я всегда обращаюсь к этой библиотеке при написании приложения консоли С#.