编程小知识之命令行解析 妖狐艹你老母 2022-05-20 06:36 150阅读 0赞 > 当前的软件开发中,图形界面已然大行其道,命令行似乎愈加式微,不过在一些场景下,命令行仍然必不可少~ 工具链的正常运作往往需要仰仗命令行,各个工具间的“沟通交流”基本都是通过命令行来完成,考虑一下 **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]了解SimpleArgument* [SimpleArgument]: https://github.com/tkokof/SimpleArgument
还没有评论,来说两句吧...