数据即代码,我和小伙伴们都惊呆了!

几个小伙伴在考虑下面这个各个语言都会遇到的问题:

创新互联公司是一家集网站建设,乌翠企业网站建设,乌翠品牌网站建设,网站定制,乌翠网站建设报价,网络营销,网络优化,乌翠网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

问题:设计一个命令行参数解析API

一个好的命令行参数解析库一般涉及到这几个常见的方面:

1) 支持方便地生成帮助信息

2) 支持子命令,比如:git包含了push, pull, commit等多种子命令

3) 支持单字符选项、多字符选项、标志选项、参数选项等多种选项和位置参数

4) 支持选项默认值,比如:–port选项若未指定认为5037

5) 支持使用模式,比如:tar命令的-c和-x是互斥选项,属于不同的使用模式

经过一番考察,小伙伴们发现了这个几个有代表性的API设计:

1. getopt():

getopt()是libc的标准函数,很多语言中都能找到它的移植版本。

 
 
 
  1. //C 
  2. while ((c = getopt(argc, argv, "ac:d:")) != -1) { 
  3.     int this_option_optind = optind ? optind : 1; 
  4.     switch (c) { 
  5.     case 'a': 
  6.         printf ("option a"); 
  7.         aopt = 1; 
  8.         break; 
  9.     case 'c': 
  10.         printf ("option c with value '%s'", optarg); 
  11.         copt = optarg; 
  12.         break; 
  13.     case 'd': 
  14.         printf ("option d with value '%s'", optarg); 
  15.         dopt = optarg; 
  16.         break; 
  17.     case '?': 
  18.         break; 
  19.     default: 
  20.         printf ("?? getopt returned character code 0%o ??", c); 
  21.     } 

getopt()的核心是一个类似printf的格式字符串的命令行参数描述串,如上面的”ac:d:”定义了”a”, “c”,”d”3个命令行参数,其中,a是一个标志符不需要参数,”c”和”d”需要跟参数。getopt()功能非常弱,只支持单个字符的标志选项和参 数选项。如果按上面的5点来比对,基本上只能说是勉强支持第3点,其他几项只能靠程序自己来实现了,所以,想直接基于getopt()实现一个像git这 样复杂的命令行参数是不可能的,只有自己来做很多的解析工作。小伙伴们看过getopt()之后一致的评价是:图样图森破。

2. Google gflags

接着,小伙伴们又发现了gflags这个Google出品C++命令行参数解析库。

 
 
 
  1. /C++ 
  2. DEFINE_bool(memory_pool, false, "If use memory pool"); 
  3. DEFINE_bool(daemon, true, "If started as daemon"); 
  4. DEFINE_string(module_id, "", "Server module id"); 
  5. DEFINE_int32(http_port, 80, "HTTP listen port"); 
  6. DEFINE_int32(https_port, 443, "HTTPS listen port"); 
  7.   
  8. int main(int argc, char** argv) { 
  9.     ::google::ParseCommandLineFlags(&argc, &argv, true); 
  10.   
  11.     printf("Server module id: %s", FLAGS_module_id.c_str()); 
  12.   
  13.     if (FLAGS_daemon) { 
  14.       printf("Run as daemon: %d", FLAGS_daemon); 
  15.     } 
  16.     if (FLAGS_memory_pool) { 
  17.       printf("Use memory pool: %d", FLAGS_daemon); 
  18.     } 
  19.   
  20.     Server server; 
  21.   
  22.     return 0; 

小伙伴们看了后不由得感叹“真心好用啊”!的确,gflags简单地通过几个宏就定义了命令行选项,基本上很好的支持了上面提到的1,3,4这几 项,比起getopt()来强多了。对于类似cp这样的小命令,gflags应该是够用了,但要达到git这种级别就显得有些单薄了。

3. Ruby Commander

接下来小伙伴们又发现了Ruby Commander库:

 
 
 
  1. //Ruby 
  2. # :name is optional, otherwise uses the basename of this executable 
  3. program :name, 'Foo Bar' 
  4. program :version, '1.0.0' 
  5. program :description, 'Stupid command that prints foo or bar.' 
  6. command :bar do |c| 
  7.   c.syntax = 'foobar bar [options]' 
  8.   c.description = 'Display bar with optional prefix and suffix' 
  9.   c.option '--prefix STRING', String, 'Adds a prefix to bar' 
  10.   c.option '--suffix STRING', String, 'Adds a suffix to bar' 
  11.   c.action do |args, options| 
  12.     options.default :prefix => '(', :suffix => ')' 
  13.     say "#{options.prefix}bar#{options.suffix}" 
  14.   end 
  15. end 
  16. $ foobar bar 
  17. # => (bar) 
  18. $ foobar bar --suffix '}' --prefix '{' 
  19. # => {bar} 

Commander库利用Ruby酷炫的语法定义了一种描述命令行参数的内部DSL,看起来相当高端大气上档次。除了上面的第5项之外,其他几项都 有很好的支持,可以说Commander库的设计基本达到了git这种级别命令行参数解析的要求。只是,要搞懂Ruby这么炫的语法和这个库的使用方法恐 怕就不如getopt()和gflags容易了。有小伙伴当场表示想要学习Ruby,但是也有小伙伴表示再看看其他库再说。

4. Lisp cmdline库

接下来,小伙伴们发现了Lisp方言Racket的cmdline库。

 
 
 
  1. //Lisp 
  2. (parse-command-line "compile" (current-command-line-arguments) 
  3.   `((once-each 
  4.      [("-v" "--verbose") 
  5.       ,(lambda (flag) (verbose-mode #t)) 
  6.       ("Compile with verbose messages")] 
  7.      [("-p" "--profile") 
  8.       ,(lambda (flag) (profiling-on #t)) 
  9.       ("Compile with profiling")]) 
  10.     (once-any 
  11.      [("-o" "--optimize-1") 
  12.       ,(lambda (flag) (optimize-level 1)) 
  13.       ("Compile with optimization level 1")] 
  14.      [("--optimize-2") 
  15.       ,(lambda (flag) (optimize-level 2)) 
  16.       (("Compile with optimization level 2," 
  17.         "which implies all optimizations of level 1"))]) 
  18.     (multi 
  19.      [("-l" "--link-flags") 
  20.       ,(lambda (flag lf) (link-flags (cons lf (link-flags)))) 
  21.       ("Add a flag <lf> for the linker" "lf")])) 
  22.    (lambda (flag-accum file) file) 
  23.    '("filename")) 

这是神马浮云啊?括号套括号,看起来很厉害的样子,但又不是很明白。看到这样的设计,有的小伙伴连评价都懒得评价了,但也有的小伙伴对Lisp越发崇拜,表示Lisp就是所谓的终极语言了,没有哪门语言能写出这么不明觉历的代码来!小伙伴们正准备打完收工,突然…

5. Node.js的LineParser库

发现了Node.js的LineParser库:

 
 
 
  1. //JavaScript 
  2. var meta = { 
  3.     program : 'adb', 
  4.     name : 'Android Debug Bridge', 
  5.     version : '1.0.3', 
  6.     subcommands : [ 'connect', 'disconnect', 'install' ], 
  7.     options : { 
  8.     flags : [ 
  9.         [ 'h', 'help', 'print program usage' ], 
  10.         [ 'r', 'reinstall', 'reinstall package' ], 
  11.         [ 'l', 'localhost', 'localhost' ] 
  12.     ], 
  13.     parameters : [ 
  14.         [ null, 'host', 'adb server hostname or IP address', null ], 
  15.         [ 'p', 'port', 'adb server port', 5037 ] 
  16.     ] 
  17.     }, 
  18.     usages : [ 
  19.     [ 'connect', ['host', '[port]'], null, 'connect to adb server', adb_connect ], 
  20.     [ 'connect', [ 'l' ], null, 'connect to the local adb server', adb_connect ], 
  21.     [ 'disconnect', null, null, 'disconnect from adb server', adb_disconnect ], 
  22.     [ 'install', ['r'], ['package'], 'install package', adb_install ], 
  23.     [ null, ['h'], null, 'help', adb_help ], 
  24.     ] 
  25. }; 
  26.   
  27. try { 
  28.     var lineparser = require('lineparser'); 
  29.     var parser = lineparser.init(meta); 
  30.     parser.parse(['install', '-r', '/pkgs/bird.apk']); // adb_install will be invoked 
  31. catch (e) { 
  32.     console.error(e); 

天啊!?这是什么?我和小伙伴们彻底惊呆了!短短十几行代码就获得了上面5点的全面支持,重要的是小伙伴们居然一下子就看懂了,没有任何的遮遮掩掩 和故弄玄虚。本来以为Ruby和Lisp很酷,小伙伴们都想马上去学Ruby和Lisp了,看到这个代码之后怎么感觉前面全是在装呢?有个小伙伴居然激动 得哭着表示:我写代码多年,以为再也没有什么代码可以让我感动,没想到这段代码如此精妙,我不由得要赞叹了,实在是太漂亮了!

小伙伴们的故事讲完了,您看懂了吗?如果没有再看一遍标题吧!

原文链接:http://coolshell.cn/articles/10337.html

新闻名称:数据即代码,我和小伙伴们都惊呆了!
分享网址:http://www.csdahua.cn/qtweb/news21/249521.html

网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网