编程小知识之命令行解析

当前的软件开发中,图形界面已然大行其道,命令行似乎愈加式微,不过在一些场景下,命令行仍然必不可少~

工具链的正常运作往往需要仰仗命令行,各个工具间的“沟通交流”基本都是通过命令行来完成,考虑一下 C 语言中 main 函数的标准定义:

// C
int main(int argc, char* argv[])
{
    // codes ...

    return EXIT_SUCCESS
}

其中的 argc 便是命令行的参数个数, 而 argv 则是各个具体的命令行参数~

当我们编写支持命令行的程序时,很多时候都不太在意用以解析命令行的相关逻辑,往往随手写些分支代码便了事了,就像这样(以 C# 代码举例):

// C#
public static void Main(string[] args)
{
    if (args.Length > 0)
    {
        if (args[0] == "-a0")
        {
            OnArg0();
        }
        else if (args[0] == "-a1")
        {
            OnArg1(Convert.ToInt32(args[1]));
        }

        // other situations here ...
    }
}

代码很简单,但其中的问题也很明显:

1. 无法处理复合的命令行参数,譬如 “-a0 -a1 100”
2. 处理非字符串参数较为繁琐,代码中需要在各处书写转换逻辑
3. 各种异常难以处理,譬如转换失败、参数错误等等

复合命令行参数的问题我们可以使用循环来解决:

// C#
public static void Main(string[] args)
{
    int index = 0;
    while (index < args.Length)
    {
        if (args[index] == "-a0")
        {
            OnArg0();
            ++index;
        }
        else if (args[index] == "-a1")
        {
            OnArg1(Convert.ToInt32(args[index + 1]));
            index += 2;
        }
        else
        {
            ++index;
        }

        // other situations here ...
    }
}

但是对于另外两个问题我们还要继续寻找解决方法~

其实解析命令行的更好方式还是使用通用逻辑单独处理,而不要使其耦合于业务逻辑之中,为此我们可以编写一个类库,封装相关解析逻辑~

秉持”最小化”接口原则,对于这个命令行解析库,我个人觉得至少要提供下面3个接口:

// add argument handler
void Add(string name, Action handler);

// remove argument handler
void Remove(string name);

// handle arguments
void Handle(string[] args);

Add接口用于添加某个命令行参数的处理函数

Remove接口则用于去除某个命令行参数的处理函数

Handle接口则是进行实际的命令行解析操作,并执行对应的命令行处理函数

有时候我们可能需要解析原始字符串,而不是分割好的参数列表,为此我们可以提供一个重载的Handle接口:

// handle raw arguments
void Handle(string rawArgs);

github上自己简单搞了一个解析库SimpleArgument,有兴趣的朋友可以看看,欢迎 pr ~

有了辅助库,命令行解析便不再恼人了,之前的代码我们可以改写成这样:

// C#
public static void Main(string[] args)
{
    var sa = new SimpleArgument();
    sa.Add("-a0", OnArg0);
    sa.Add<int>("-a1", OnArg1);

    sa.Handle(args);
    // or we can parse raw args directly
    //sa.Handle("-a0 -a1 100");
}

代码简洁明了,比起之前那些交织的分支(循环)要好上不少~

编程已经足够复杂了,一些机械的、枯燥的(往往也是容易出错的)逻辑就交给类库(或者说自动化)去解决吧~

注 : 点击这里了解SimpleArgument

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP在线

PHP7性能提升之后的思考

导读] 时下不少人拿PHP7的高性能与HHVM来做比较,那么问题来了:随着PHP7性能的提升,我们能预测出未来PHP这门语言会用PHP写出来么?最经典的实例就是...

36880
来自专栏UDNZ

【译】Go 语言实践:编写可维护的程序的建议

本文为 QCon 2018 上海站主题演讲嘉宾、Heptio 资深工程师、著名 Go 语言专家 David Cheney 关于 Go 语言实践的英文分享。为方便...

53480
来自专栏魏琼东

一步一步教你使用AgileEAS.NET基础类库进行应用开发-WinForm应用篇-实例一个模块(商品字典)

        本文是一步一步教你使用AgileEAS.NET基础进行应用开发系统的WinForm应用篇的开篇,从本文起开始大家将看到一个距离真实应用非常接的开...

20950
来自专栏CDA数据分析师

热度碾压 Java、C#、C++的 Python,为什么速度那么慢?

眼下 Python 异常火爆,不论是 DevOps、数据科学、Web 开发还是安全领域,都在用 Python——但是它在速度上却没有任何优势。

21310
来自专栏一名合格java开发的自我修养

java使用Map做缓存你真的用对了吗?弱引用WeakHashMap了解一下

序:使用java的Map做缓存,你是否考虑过容量导致的OOM问题,是否考虑命中率对性能的影响??

39310
来自专栏SDNLAB

Ryu的一些设计方法解读

作为一个业余研究Ryu的软件工程师,一直惊叹于Ryu设计的优雅与简洁。一年多坚持下来,也有自己的一些收获,写出来和大家分享一下。 我们的故事从@set_ev_c...

33360
来自专栏coding for love

JS常用设计模式解析02-策略模式

在于都本文之前,希望大家能够先阅读以下JS进阶系列03-JS面向对象的三大特征之多态这篇文章,了解JS的多态。在这篇文章,我们举了一个例子,就是选拔官员选拔合唱...

14530
来自专栏LuckQI

Java核心技术讲解学习

15820
来自专栏Danny的专栏

【MyEclipse】——MyEclipse建立树形结构包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

12510
来自专栏游戏杂谈

php正则表达式的分组捕获

经过测试,发现php正则表达式获取分组捕获是从$0开始,而平时工作中JavaScript中的正则是$1..$9

17430

扫码关注云+社区

领取腾讯云代金券