新聞中心
幾個(gè)小伙伴在考慮下面這個(gè)各個(gè)語(yǔ)言都會(huì)遇到的問題:

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),烏翠企業(yè)網(wǎng)站建設(shè),烏翠品牌網(wǎng)站建設(shè),網(wǎng)站定制,烏翠網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,烏翠網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
問題:設(shè)計(jì)一個(gè)命令行參數(shù)解析API
一個(gè)好的命令行參數(shù)解析庫(kù)一般涉及到這幾個(gè)常見的方面:
1) 支持方便地生成幫助信息
2) 支持子命令,比如:git包含了push, pull, commit等多種子命令
3) 支持單字符選項(xiàng)、多字符選項(xiàng)、標(biāo)志選項(xiàng)、參數(shù)選項(xiàng)等多種選項(xiàng)和位置參數(shù)
4) 支持選項(xiàng)默認(rèn)值,比如:–port選項(xiàng)若未指定認(rèn)為5037
5) 支持使用模式,比如:tar命令的-c和-x是互斥選項(xiàng),屬于不同的使用模式
經(jīng)過一番考察,小伙伴們發(fā)現(xiàn)了這個(gè)幾個(gè)有代表性的API設(shè)計(jì):
1. getopt():
getopt()是libc的標(biāo)準(zhǔn)函數(shù),很多語(yǔ)言中都能找到它的移植版本。
- //C
- while ((c = getopt(argc, argv, "ac:d:")) != -1) {
- int this_option_optind = optind ? optind : 1;
- switch (c) {
- case 'a':
- printf ("option a");
- aopt = 1;
- break;
- case 'c':
- printf ("option c with value '%s'", optarg);
- copt = optarg;
- break;
- case 'd':
- printf ("option d with value '%s'", optarg);
- dopt = optarg;
- break;
- case '?':
- break;
- default:
- printf ("?? getopt returned character code 0%o ??", c);
- }
- }
getopt()的核心是一個(gè)類似printf的格式字符串的命令行參數(shù)描述串,如上面的”ac:d:”定義了”a”, “c”,”d”3個(gè)命令行參數(shù),其中,a是一個(gè)標(biāo)志符不需要參數(shù),”c”和”d”需要跟參數(shù)。getopt()功能非常弱,只支持單個(gè)字符的標(biāo)志選項(xiàng)和參 數(shù)選項(xiàng)。如果按上面的5點(diǎn)來比對(duì),基本上只能說是勉強(qiáng)支持第3點(diǎn),其他幾項(xiàng)只能靠程序自己來實(shí)現(xiàn)了,所以,想直接基于getopt()實(shí)現(xiàn)一個(gè)像git這 樣復(fù)雜的命令行參數(shù)是不可能的,只有自己來做很多的解析工作。小伙伴們看過getopt()之后一致的評(píng)價(jià)是:圖樣圖森破。
2. Google gflags
接著,小伙伴們又發(fā)現(xiàn)了gflags這個(gè)Google出品C++命令行參數(shù)解析庫(kù)。
- /C++
- DEFINE_bool(memory_pool, false, "If use memory pool");
- DEFINE_bool(daemon, true, "If started as daemon");
- DEFINE_string(module_id, "", "Server module id");
- DEFINE_int32(http_port, 80, "HTTP listen port");
- DEFINE_int32(https_port, 443, "HTTPS listen port");
- int main(int argc, char** argv) {
- ::google::ParseCommandLineFlags(&argc, &argv, true);
- printf("Server module id: %s", FLAGS_module_id.c_str());
- if (FLAGS_daemon) {
- printf("Run as daemon: %d", FLAGS_daemon);
- }
- if (FLAGS_memory_pool) {
- printf("Use memory pool: %d", FLAGS_daemon);
- }
- Server server;
- return 0;
- }
小伙伴們看了后不由得感嘆“真心好用啊”!的確,gflags簡(jiǎn)單地通過幾個(gè)宏就定義了命令行選項(xiàng),基本上很好的支持了上面提到的1,3,4這幾 項(xiàng),比起getopt()來強(qiáng)多了。對(duì)于類似cp這樣的小命令,gflags應(yīng)該是夠用了,但要達(dá)到git這種級(jí)別就顯得有些單薄了。
3. Ruby Commander
接下來小伙伴們又發(fā)現(xiàn)了Ruby Commander庫(kù):
- //Ruby
- # :name is optional, otherwise uses the basename of this executable
- program :name, 'Foo Bar'
- program :version, '1.0.0'
- program :description, 'Stupid command that prints foo or bar.'
- command :bar do |c|
- c.syntax = 'foobar bar [options]'
- c.description = 'Display bar with optional prefix and suffix'
- c.option '--prefix STRING', String, 'Adds a prefix to bar'
- c.option '--suffix STRING', String, 'Adds a suffix to bar'
- c.action do |args, options|
- options.default :prefix => '(', :suffix => ')'
- say "#{options.prefix}bar#{options.suffix}"
- end
- end
- $ foobar bar
- # => (bar)
- $ foobar bar --suffix '}' --prefix '{'
- # => {bar}
Commander庫(kù)利用Ruby酷炫的語(yǔ)法定義了一種描述命令行參數(shù)的內(nèi)部DSL,看起來相當(dāng)高端大氣上檔次。除了上面的第5項(xiàng)之外,其他幾項(xiàng)都 有很好的支持,可以說Commander庫(kù)的設(shè)計(jì)基本達(dá)到了git這種級(jí)別命令行參數(shù)解析的要求。只是,要搞懂Ruby這么炫的語(yǔ)法和這個(gè)庫(kù)的使用方法恐 怕就不如getopt()和gflags容易了。有小伙伴當(dāng)場(chǎng)表示想要學(xué)習(xí)Ruby,但是也有小伙伴表示再看看其他庫(kù)再說。
4. Lisp cmdline庫(kù)
接下來,小伙伴們發(fā)現(xiàn)了Lisp方言Racket的cmdline庫(kù)。
- //Lisp
- (parse-command-line "compile" (current-command-line-arguments)
- `((once-each
- [("-v" "--verbose")
- ,(lambda (flag) (verbose-mode #t))
- ("Compile with verbose messages")]
- [("-p" "--profile")
- ,(lambda (flag) (profiling-on #t))
- ("Compile with profiling")])
- (once-any
- [("-o" "--optimize-1")
- ,(lambda (flag) (optimize-level 1))
- ("Compile with optimization level 1")]
- [("--optimize-2")
- ,(lambda (flag) (optimize-level 2))
- (("Compile with optimization level 2,"
- "which implies all optimizations of level 1"))])
- (multi
- [("-l" "--link-flags")
- ,(lambda (flag lf) (link-flags (cons lf (link-flags))))
- ("Add a flag <lf> for the linker" "lf")]))
- (lambda (flag-accum file) file)
- '("filename"))
這是神馬浮云啊?括號(hào)套括號(hào),看起來很厲害的樣子,但又不是很明白??吹竭@樣的設(shè)計(jì),有的小伙伴連評(píng)價(jià)都懶得評(píng)價(jià)了,但也有的小伙伴對(duì)Lisp越發(fā)崇拜,表示Lisp就是所謂的終極語(yǔ)言了,沒有哪門語(yǔ)言能寫出這么不明覺歷的代碼來!小伙伴們正準(zhǔn)備打完收工,突然…
5. Node.js的LineParser庫(kù)
發(fā)現(xiàn)了Node.js的LineParser庫(kù):
- //JavaScript
- var meta = {
- program : 'adb',
- name : 'Android Debug Bridge',
- version : '1.0.3',
- subcommands : [ 'connect', 'disconnect', 'install' ],
- options : {
- flags : [
- [ 'h', 'help', 'print program usage' ],
- [ 'r', 'reinstall', 'reinstall package' ],
- [ 'l', 'localhost', 'localhost' ]
- ],
- parameters : [
- [ null, 'host', 'adb server hostname or IP address', null ],
- [ 'p', 'port', 'adb server port', 5037 ]
- ]
- },
- usages : [
- [ 'connect', ['host', '[port]'], null, 'connect to adb server', adb_connect ],
- [ 'connect', [ 'l' ], null, 'connect to the local adb server', adb_connect ],
- [ 'disconnect', null, null, 'disconnect from adb server', adb_disconnect ],
- [ 'install', ['r'], ['package'], 'install package', adb_install ],
- [ null, ['h'], null, 'help', adb_help ],
- ]
- };
- try {
- var lineparser = require('lineparser');
- var parser = lineparser.init(meta);
- parser.parse(['install', '-r', '/pkgs/bird.apk']); // adb_install will be invoked
- }
- catch (e) {
- console.error(e);
- }
天?。??這是什么?我和小伙伴們徹底驚呆了!短短十幾行代碼就獲得了上面5點(diǎn)的全面支持,重要的是小伙伴們居然一下子就看懂了,沒有任何的遮遮掩掩 和故弄玄虛。本來以為Ruby和Lisp很酷,小伙伴們都想馬上去學(xué)Ruby和Lisp了,看到這個(gè)代碼之后怎么感覺前面全是在裝呢?有個(gè)小伙伴居然激動(dòng) 得哭著表示:我寫代碼多年,以為再也沒有什么代碼可以讓我感動(dòng),沒想到這段代碼如此精妙,我不由得要贊嘆了,實(shí)在是太漂亮了!
小伙伴們的故事講完了,您看懂了嗎?如果沒有再看一遍標(biāo)題吧!
原文鏈接:http://coolshell.cn/articles/10337.html
標(biāo)題名稱:數(shù)據(jù)即代碼,我和小伙伴們都驚呆了!
網(wǎng)站鏈接:http://m.fisionsoft.com.cn/article/cdgscgg.html


咨詢
建站咨詢
