C#/.NET 使用 CommandLineParser 來標准化地解析命令行


CommandLineParser 是一款用於解析命令行參數的 NuGet 包。你只需要關注你的業務,而命令行解析只需要極少量的配置代碼。

本文將介紹如何使用 CommandLineParser 高效寫出自己程序的命令行解析部分。


 

 

NuGet 包和 GitHub 開源倉庫

最簡單的命令行解析

using System;
using System.Collections.Generic;
using CommandLine;

namespace Walterlv.Demo
{
    class Program
    {
        public class Options
        {
            [Option('f', "file", Required = true, HelpText = "需要處理的文件。")]
            public IEnumerable<string> Files { get; set; }

            [Option('o', "override", Required = false, HelpText = "是否覆蓋原有文件。")]
            public bool Override { get; set; }
        }

        static void Main(string[] args)
        {
            Parser.Default.ParseArguments<Options>(args).WithParsed(Run);
        }

        private static void Run(Options option)
        {
            // 使用解析后的命令行參數進行操作。
            foreach (var file in option.Files)
            {
                var verb = option.Override ? "覆蓋" : "使用";
                Console.WriteLine($"walterlv 正在{verb}文件 {file}");
            }
        }
    }
}

這個簡單的 Demo 程序使用 Options 類來封裝命令行參數,Parser.Default.ParseArguments 解析到的參數將存入 Options 類型的實例中。而只需要加上 WithParsed 即可在一個新的方法中使用我們解析后的 Options 實例。

這時,在命令行中就可以使用命令了:

dotnet demo.dll -f C:\Users\lvyi\Desktop\Test.txt

在命令行中使用命令

由於我們標記 Files 是必要屬性,所以如果此參數沒有指定,將返回命令行的使用說明。此使用說明中就包含了我們在 Option 參數中編寫的 HelpText

如果你的 Options 類中單次是多單詞的短語,那么建議在指定名稱的時候為每一個單詞之間添加一個空格。這樣參數就不會讓多個單詞連成一片難以辨認。

例如:

public class Options
{
    [Option("long-name", Required = true, HelpText = "需要處理的文件。")]
    public string LongName { get; set; }
}

那么命令是:

dotnet demo.dll --long-name xxx

如果不指定,那么就是 --longname,這顯然不好看。

包含多個方法的命令行解析

如果一個命令行程序只做一件事情,那么以上代碼足以應付大多數的情況。可是有時候一個命令行程序是為了做一類事情的 —— 典型的例子就是 git 程序。當你運行 git 的時候,你可以在 git 后面加一個謂詞(動詞),表示執行的是哪一個命令。后面的參數是每個命令都不同的,並且第一個參數是不用指定名稱的。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using CommandLine;

namespace Walterlv.Demo
{
    [Verb("check", HelpText = "檢查")]
    class CheckOptions
    {
        [Value(0, HelpText = "一個 .sln 文件,一個或者多個 .csproj 文件。")]
        public IEnumerable<string> InputFiles { get; set; }
    }

    [Verb("fix", HelpText = "修復")]
    class FixOptions
    {
        [Value(0, HelpText = "一個 .sln 文件,一個或者多個 .csproj 文件。")]
        public IEnumerable<string> InputFiles { get; set; }

        [Option('o', "outputFiles", Required = true, HelpText = "修復之后的文件集合。")]
        public IEnumerable<string> OutputFiles { get; set; }

        [Option(Required = false, HelpText = "是否自動決定版本號,這將使用沖突版本號中的最新版本。")]
        public bool AutoVersion { get; set; }
    }

    class Program
    {
        static int Main(string[] args)
        {
            var exitCode = Parser.Default.ParseArguments<CheckOptions, FixOptions>(args)
                .MapResult(
                    (CheckOptions o) => CheckSolutionOrProjectFiles(o),
                    (FixOptions o) => FixSolutionOrProjectFiles(o),
                    error => 1);
            return exitCode;
        }

        private static int CheckSolutionOrProjectFiles(CheckOptions options)
        {
            return 0;
        }

        private static int FixSolutionOrProjectFiles(FixOptions options)
        {
            return 0;
        }
    }
}

對於這一段程序,我們可以使用兩種不同的謂詞來執行命令:

dotnet demo.dll check C:\Users\lvyi\Desktop\Test\Test.csproj
dotnet demo.dll fix C:\Users\lvyi\Desktop\Test\Test.csproj -o C:\Users\lvyi\Desktop\TestFix\Test.csproj

Verb,Option 和 Value

Verb 是在一個命令行選項的 Option 類上標記的,用於指定命令的類別。每一個 Verb 標記的類別都可以有自己獨立的一套命令行參數。

Option 是命名的命令行參數。在命令行中,你必須指定命令行縮寫或者全稱來指定命令行參數的不同類型。

Value 是命令行的無名參數,它是靠在命令行謂詞后面的參數位置來確定解析到哪一個屬性上的。


參考資料


我的博客會首發於 https://walterlv.com/,而 CSDN 和博客園僅從其中摘選發布,而且一旦發布了就不再更新。

知識共享許可協議

本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名呂毅(包含鏈接:https://blog.csdn.net/wpwalter),不得用於商業目的,基於本文修改后的作品務必以相同的許可發布。如有任何疑問,請與我聯系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM