programing

C#에서 명령줄 인수를 구문 분석하는 가장 좋은 방법은 무엇입니까?

muds 2023. 5. 1. 22:05
반응형

C#에서 명령줄 인수를 구문 분석하는 가장 좋은 방법은 무엇입니까?

변수를 하는 콘솔 프로그램을 는 매변수사는콘솔응프만용을로들램다때있니습수사에 할 수 .Main(string[] args).

과거에는 단순히 배열을 인덱싱/루프하고 몇 가지 정규식을 수행하여 값을 추출했습니다.그러나 명령이 더 복잡해지면 구문 분석이 상당히 어려워질 수 있습니다.

관심사는 다음과 같습니다.

  • 사용하는 라이브러리
  • 사용하는 패턴

명령이 항상 여기에 답변된 것과 같은 일반적인 표준을 준수한다고 가정합니다.

저는 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에 대한 Ivo Manolov의 블로그에서 이를 검토해 보는 것을 강력히 추천합니다.

// 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://github.com/mono/mono/tree/master/mcs/class/Mono.Options/ 을 보세요.

모든 사람들이 자신만의 애완동물 명령줄 파서를 가지고 있는 것처럼 보이는데, 내 것도 추가하는 것이 좋을 것 같습니다 :).

http://bizark.codeplex.com/

이 라이브러리에는 명령줄의 값으로 클래스를 초기화하는 명령줄 파서가 포함되어 있습니다.그것은 많은 특징들을 가지고 있습니다 (저는 수년간 그것을 쌓아왔습니다).

설명서에서...

BizArk 프레임워크의 명령줄 구문 분석에는 다음과 같은 주요 기능이 있습니다.

  • 자동 초기화:클래스 속성은 명령줄 인수에 따라 자동으로 설정됩니다.
  • 기본 속성:속성 이름을 지정하지 않고 값을 보냅니다.
  • 값 변환:BizArk에도 포함된 강력한 ConvertEx 클래스를 사용하여 값을 올바른 유형으로 변환합니다.
  • 부울 플래그:플래그는 단순히 인수(예, true의 경우 /b, false의 경우 /b-)를 사용하거나 true/false, yes/no 등의 값을 추가하여 지정할 수 있습니다.
  • 인수 배열:명령줄 이름 뒤에 여러 값을 추가하여 배열로 정의된 속성을 설정하기만 하면 됩니다.예, /x12 3은 x를 {1, 2, 3} 배열로 채웁니다(x가 정수 배열로 정의되었다고 가정).
  • 명령줄 별칭:속성은 해당 속성에 대해 여러 명령줄 별칭을 지원할 수 있습니다.예를 들어 도움말에서 별칭 ?을 사용합니다.
  • 부분 이름 인식:전체 이름이나 별칭의 철자를 입력할 필요는 없으며, 구문 분석기가 속성/별명을 다른 이름과 구분할 수 있을 정도의 철자만 입력하면 됩니다.
  • ClickOnce 지원: ClickOnce 배포된 응용 프로그램에 대한 URL의 쿼리 문자열로 속성이 지정된 경우에도 속성을 초기화할 수 있습니다.명령줄 초기화 방법은 클릭 한 번으로 실행 중인지 여부를 감지하여 코드를 사용할 때 변경할 필요가 없습니다.
  • 자동으로 /? 도움말을 만듭니다.여기에는 콘솔의 너비를 고려한 적절한 포맷이 포함됩니다.
  • 명령줄 인수를 파일에 로드/저장:이 기능은 여러 번 실행하려는 크고 복잡한 명령줄 인수 집합이 여러 개 있는 경우 특히 유용합니다.

얼마 전에 C# 명령줄 인수 구문 분석기를 작성했습니다.사이트: http://www.codeplex.com/CommandLineArguments

CLAP(명령줄 인수 파서)는 사용 가능한 API를 가지고 있으며 훌륭하게 문서화되어 있습니다.매개변수에 주석을 달면서 방법을 만듭니다.https://github.com/adrianaisemberg/CLAP

이 문제에 대한 수많은 해결책이 있습니다.완전성을 위해 그리고 누군가가 원한다면 대안을 제공하기 위해 저는 구글 코드 라이브러리에 있는 두 개의 유용한 클래스에 대해 이 답변을 추가합니다.

첫 번째는 명령줄 매개 변수 구문 분석만 담당하는 ArgumentList입니다.스위치 '/x:y' 또는 '-x=y'에 의해 정의된 이름-값 쌍을 수집하고 'filename' 항목 목록도 수집합니다.기본적인 사용법에 대해서는 여기에서 설명합니다. 여기에서 클래스를 확인하십시오.

두 번째 부분은 명령입니다.에서 완전한 기능을 갖춘 명령줄 응용 프로그램을 만드는 인터프리터입니다.넷 클래스.예를 들어,

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

위의 예제 코드를 사용하여 다음을 실행할 수 있습니다.

프로그램.exe DoSomething "문자열 값" 5

또는 --

프로그램.exe do something /ivalue=5 -svalue:"string value"

그렇게 간단하거나 필요한 만큼 복잡합니다.소스 코드를 검토하거나, 도움말보거나, 이진 파일을 다운로드할 수 있습니다.

저는 그것을 좋아합니다. 왜냐하면 당신은 필요하든 아니든 논쟁에 대해 "규칙을 정의"할 수 있기 때문입니다.

또는 유닉스 사용자라면 GNU Getopt를 좋아할 수도 있습니다.NET 포트.

당신은 내 러그를 좋아할지도 모릅니다.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);
        }
    }
}

편집: 이것은 제 프로젝트이므로 이 답변이 제3자의 지지로 간주되어서는 안 됩니다.즉, 제가 작성하는 모든 명령줄 기반 프로그램에 사용합니다. 이 프로그램은 오픈 소스이며 다른 사람들이 혜택을 받을 수 있기를 바랍니다.

http://www.codeplex.com/commonlibrarynet 명령줄 인수 파서가 있습니다.

다음을 사용하여 인수를 구문 분석할 수 있습니다.
설정
인 통화
한줄 string 는 한 줄로 되어 있습니다.

다음과 같은 작업을 처리할 수 있습니다.

-config:QA - 시작 날짜:${today} - 지역:'뉴욕의 설정 01

그것은 매우 사용하기 쉽습니다.

이것은 제가 노벨을 기반으로 작성한 핸들러입니다.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;
    }
}

제가 개인적으로 가장 좋아하는 것은 피터 팔로타스의 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 (객체를 목록에 추가합니다 - 개체는 이름(문자열), value(int) 및 boolean flag(현재 추가된 모든 개체를 나열합니다).

먼저, '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;
    }
}

이 명령에는 명령이 사용됩니다.인스턴스를 매개 변수로 입력합니다. 다음으로 정의합니다.

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

다음은 '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
  -------------------------------------

파워셸 명령어입니다.

commandlet에 지정된 특성, 유효성 검사 지원, 매개 변수 집합, 파이프라이닝, 오류 보고, 도움말 및 반환되는 모든 항목을 기준으로 파워셸이 수행한 구문 분석.다른 명령어에 사용할 NET 개체입니다.

시작하는 데 도움이 되는 몇 가지 링크:

C# CLI는 제가 작성한 매우 간단한 명령줄 인수 구문 분석 라이브러리입니다.문서화되어 있고 오픈 소스입니다.

징기스 명령줄 파서는 약간 구식일 수 있지만 기능이 매우 완벽하고 저에게 잘 맞습니다.

저는 오픈 소스 라이브러리 CSSharpOptParse를 제안합니다.명령행을 구문 분석하고 사용자 정의를 수화합니다.명령줄 입력이 있는 NET 개체입니다.저는 C# 콘솔 애플리케이션을 작성할 때 항상 이 라이브러리를 사용합니다.

apache commons CLI API의 .net 포트를 사용하십시오.이것은 아주 잘 작동합니다.

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

언급URL : https://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c

반응형