zoukankan      html  css  js  c++  java
  • C#命令行参数解析库System.CommandLine介绍

    命令行参数

    平常在日常的开发过程中,会经常用到命令行工具。如cmd下的各种命令。

    以下为sc命令执行后的截图,可以看到,由于没有输入任何附带参数,所以程序并未执行任何操作,只是输出了描述和用法。

    系统在创建一个新进程时,会传一个命令行给它,也就是命令行字符串。

    程序需要对命令行字符串进行解析,并执行相应操作。

    如使用sc query可以查询当前系统的服务:

    在C#中的控制台程序中,Main函数中传入的args字符串数组,就是系统传入进程的命令行参数。

    在构建具有复杂命令行参数的控制台程序时 ,手动解析参数就变得非常麻烦。这里推荐一个开源的库,可以更加方便的解析命令行参数。

    System.CommandLine介绍

    System.CommandLine是一个基于.Net Standard 2.0(支持.Net FrameWork 4.6.1.2+和.Net Core 2.0+)的命令行参数解析库,项目地址 https://github.com/dotnet/command-line-api,目前,该项目还是属于beta状态,期待以后的正式版本。

    由于不是正式版本,在Nuget中引用时,需要钩上Include prerelease,才能找到这个包。

    System.CommandLine的一些基本概念

    Token(标记)

    命令行的每个单词都是一个标记,如下面的"sc"、"query"和"eventlog"都是一个Token

    Commands(命令)

    Commands就是应用程序根据Token执行相应的操作(在System.CommandLine库中,对应 Command类)

    Root Command(根命令)

    根命令是代表可执行程序本身的Commands,如 sc(在System.CommandLine库中,对应RootCommand类)

    SubCommands(子命令)

    一些命令行程序会有SubCommands,如上面的sc query中的query就是子命令(在System.CommandLine,对应Command类)

    Options(可选项)

    Options就是传递给Commands的命名参数,如 app -myoption123中的 -myoption 123就是一个Options

    Argument(参数)

    参数就是传递给选项或命令的值。

    说明:

    常规的调用如下:

    xx.exe   [options]   <argument>  [command]

    Delimiters(分隔符)

    分隔符就是把Options的命令和值分开的符号

    如下三种写法都是一样的,可以使用空格、=或 :符号

    app -myoption 123

    app -myoption=123

    app -myoption:123

    Aliases(别名)

    可以为命令或选项设置较短的别名,如

    -v, --verbose   

    --o, --option 

    System.CommandLine使用

    在下面的示例中,我们会构建一个简单的控制台爬虫工具。

    1、使用Visual Studio 2019创建一个.Net Core控制台程序crawler-line

    2、导入System.CommandLine包

     

    3、创建一个RootCommand

     1 var rootCommand = new RootCommand
     2             {
     3                 new Argument<string>(
     4                     "url","web site url"),
     5                 new Option<bool>(new string[]{ "--gethtml" ,"-html"},"Get html source"),
     6                 new Option<bool>(new string[]{ "--getimage" ,"-image"},"Get images"),
     7                 new Option<bool>(new string[]{ "--regex-option" ,"-regex"},"Use regex"),
     8                 new Option<bool>(new string[]{ "--htmlagilitypack-option", "-agpack"},"Use HtmlAgilityPack"),
     9                 new Option<bool>(new string[]{ "--anglesharp-option", "-agsharp"},"Use AngleSharp"),
    10                 new Option<string>(new string[]{ "--download-path" ,"-path"},"Designate download path"),13             };

    说明:

    可通过Option类的构造函数重载,为Option指定默认值。

    1  public Option(string alias, Func<T> getDefaultValue, string? description = null);

    如上面的-path Option,指定默认值为D:download,如下:

    1 new Option<string>(new string[]{ "--download-path" ,"-path"},getDefaultValue:()=>"D:\download","Designate download path"),

    也可以先实例化RootCommand对象,再通过Add的方式添加Argument和Option,如下:

    1 var rootCommand = new RootCommand();
    2 //添加 Argument
    3 rootCommand.AddArgument(new Argument<string>("url","web site url"));
    4 //添加 Option
    5 rootCommand.AddOption(new Option<string>(new string[] {"--download-path","-path" },"download path"));

    4、添加当前命令行程序的描述信息

    1 rootCommand.Description = ".Net Core command-line crawler.";

    5、解析Argument和Option

    rootCommand.Handler = CommandHandler.Create<string, bool, bool, bool, bool, bool, string>((string url, bool html, bool image, bool regex, bool agpack, bool agsharp, string path) => {
                    
                });

    如果觉得参数太长,可以封装成类,再进行调用,如下:

     1 public class CrawlerOption
     2     {
     3         public string Url { get; set; }
     4         public bool GetHtml { get; set; }
     5         public bool GetImage { get; set; }
     6         public bool RegexOption { get; set; }
     7         public bool HtmlagilitypackOption { get; set; }
     8         public bool AnglesharpOption { get; set; }
     9         public string DownloadPath { get; set; }
    10     }
    1 rootCommand.Handler = CommandHandler.Create<CrawlerOption>((crawlerOption) =>
    2             {
    3 
    4             })

    6、添加Command并为Command添加处理函数

    1             //添加 Command
    2             var githubCommand = new Command("github", "fork me on github");
    3             //添加 Command的处理函数
    4             githubCommand.Handler = CommandHandler.Create(() => { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("cmd", $"/c start https://github.com/zhaotianff/Crawler-Line")); });5             //将Command添加 到RootCommand
    6             rootCommand.AddCommand(githubCommand);

    说明:

    1、RootCommand是顶级命令,RootCommand可以添加Command,Command又可以再添加SubCommand。如此可以无限循环,没有限制 。但建议还是不要添加太多级的Command,调用的时候会不太友好 

    2、Command和RootCommand原理一样,如果需要为Command添加Argument、Option和Command,可以参照前面的示例

    7、调用解析

    1 return rootCommand.InvokeAsync(args).Result;

    8、调用示例

    #执行github command
    crawler-line.exe github
    #执行github subcommand
    crawler-line.exe github sub
    #执行argument option
    crawler-line.exe http://www.baidu.com -path "D:	est"

    特别提示:

    前面示例中,都是为RootCommand添加的Argument和Option,如果又指定 -path(Option),又执行github(Command)肯定会失败。因为github这个命令是RootCommand的子命令,而-path选项是为RootCommand添加的

    示例代码

    https://github.com/zhaotianff/Crawler-Line/tree/v1.0

    life runs on code

    作者: zhaotianff

    转载请注明出处

  • 相关阅读:
    在vs2008中集成JavaScript Lint检查JavaScript语法
    (转载)SQL分页语句
    设置出错页
    判断2个输入框至少输入1个
    C#获取用户桌面等特殊系统路径
    创建存储过程的代码
    SqlParameter关于Like的传参数无效问题
    (转)利用Office里面的OWC组件进行画图
    firefox3不能获得html file的全路径的问题
    (转)使用ASP.NET上传图片汇总
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/13507665.html
Copyright © 2011-2022 走看看