日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
數(shù)據(jù)即代碼,我和小伙伴們都驚呆了!

幾個小伙伴在考慮下面這個各個語言都會遇到的問題:

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設,烏翠企業(yè)網(wǎng)站建設,烏翠品牌網(wǎng)站建設,網(wǎng)站定制,烏翠網(wǎng)站建設報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,烏翠網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

問題:設計一個命令行參數(shù)解析API

一個好的命令行參數(shù)解析庫一般涉及到這幾個常見的方面:

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

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

3) 支持單字符選項、多字符選項、標志選項、參數(shù)選項等多種選項和位置參數(shù)

4) 支持選項默認值,比如:–port選項若未指定認為5037

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

經(jīng)過一番考察,小伙伴們發(fā)現(xiàn)了這個幾個有代表性的API設計:

1. getopt():

getopt()是libc的標準函數(shù),很多語言中都能找到它的移植版本。

 
 
 
  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的格式字符串的命令行參數(shù)描述串,如上面的”ac:d:”定義了”a”, “c”,”d”3個命令行參數(shù),其中,a是一個標志符不需要參數(shù),”c”和”d”需要跟參數(shù)。getopt()功能非常弱,只支持單個字符的標志選項和參 數(shù)選項。如果按上面的5點來比對,基本上只能說是勉強支持第3點,其他幾項只能靠程序自己來實現(xiàn)了,所以,想直接基于getopt()實現(xiàn)一個像git這 樣復雜的命令行參數(shù)是不可能的,只有自己來做很多的解析工作。小伙伴們看過getopt()之后一致的評價是:圖樣圖森破。

2. Google gflags

接著,小伙伴們又發(fā)現(xiàn)了gflags這個Google出品C++命令行參數(shù)解析庫。

 
 
 
  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

接下來小伙伴們又發(fā)現(xiàn)了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酷炫的語法定義了一種描述命令行參數(shù)的內部DSL,看起來相當高端大氣上檔次。除了上面的第5項之外,其他幾項都 有很好的支持,可以說Commander庫的設計基本達到了git這種級別命令行參數(shù)解析的要求。只是,要搞懂Ruby這么炫的語法和這個庫的使用方法恐 怕就不如getopt()和gflags容易了。有小伙伴當場表示想要學習Ruby,但是也有小伙伴表示再看看其他庫再說。

4. Lisp cmdline庫

接下來,小伙伴們發(fā)現(xiàn)了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越發(fā)崇拜,表示Lisp就是所謂的終極語言了,沒有哪門語言能寫出這么不明覺歷的代碼來!小伙伴們正準備打完收工,突然…

5. Node.js的LineParser庫

發(fā)現(xiàn)了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


分享文章:數(shù)據(jù)即代碼,我和小伙伴們都驚呆了!
文章地址:http://www.5511xx.com/article/cdgscgg.html