使用 getopt 進(jìn)行命令行處理_第1頁
使用 getopt 進(jìn)行命令行處理_第2頁
使用 getopt 進(jìn)行命令行處理_第3頁
使用 getopt 進(jìn)行命令行處理_第4頁
使用 getopt 進(jìn)行命令行處理_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、developerWorks.etopt()進(jìn)行命令行處理理復(fù)雜命令行級(jí)別:中級(jí)文Chris Herborth ( HYPERLINK mailto:chrish chrish),自 由撰稿人,作家2006年5月25日苣所有UNIX程序甚至那些具有圖形用戶界面(graphical user interface, GUI)的程序,都能接受和處理 命令行選項(xiàng)。對(duì)于某些程序,這是與其他程序或用戶進(jìn)行交互的主要手段。具有可靠的復(fù)雜命令行參數(shù)處 理機(jī)制,會(huì)使得您的應(yīng)用程序更好、更有用。不過很多開發(fā)人員都將其寶貴的時(shí)間花在了編寫自己的命令 行解析器,卻不使用getopt(),而后者是一個(gè)專門設(shè)計(jì)來減輕命令

2、行處理負(fù)擔(dān)的庫函數(shù)。請(qǐng)閱讀本文, 以了解如何讓getopt()在全局結(jié)構(gòu)中記錄命令參數(shù),以便隨后隨時(shí)在整個(gè)程序中使用。引言在早期的UNIX中,其命令行環(huán)境(當(dāng)時(shí)的唯一用戶界面)包含著數(shù)十種小的文本處理工具。這些工具 非常小,通常可很好地完成一項(xiàng)工作。這些工具通過較長的命令管道鏈接在一起,前面的程序?qū)⑵漭敵鰝?遞給下一個(gè)程序以作為輸入,整個(gè)過程由各種命令行選項(xiàng)和參數(shù)加以控制。正是UNIX的這方面的特征使其成為了極為強(qiáng)大的處理基于本文的數(shù)據(jù)的環(huán)境,而這也是其在公司環(huán)境中 的最初用途之一。在命令管道的一端輸入一些文本,然后在另一端檢索經(jīng)過處理的輸出。命令行選項(xiàng)和參數(shù)控制UNIX程序,告知它們?nèi)绾蝿?dòng)作

3、。作為開發(fā)人員,您要負(fù)責(zé)從傳遞給您程序的 main()函數(shù)的命令行發(fā)現(xiàn)用戶的意圖。本文將演示如何使用標(biāo)準(zhǔn)getopt()和getopt_long()函 數(shù)來簡化命令行處理工作,并討論了一項(xiàng)用于跟蹤命令行選項(xiàng)的技術(shù)。一開始之前本文包含的示例代碼(請(qǐng)參見下載)是使用C開發(fā)工具(。Development Tooling, CDT)在 Eclipse 3.1反 中編寫的;getopt_demo和getopt_long_demo項(xiàng)目是Managed Make項(xiàng)目,均使用CDT的程序生 成規(guī)則構(gòu)建。在項(xiàng)目中沒有包含Makefile,如果需要在Eclipse外編譯代碼,可以自己方便地生成一個(gè)。如果尚未嘗試過

4、Eclipse (請(qǐng)參閱參考資料),真的應(yīng)該嘗試一下這是一個(gè)優(yōu)秀的集成開發(fā)環(huán)境(integrated development environment, IDE),其每個(gè)新版本都有較大的提升。這是來自“強(qiáng)硬派” EMACS和Makefile開發(fā)人員的作品。命令行在編寫新程序時(shí),首先遇到的障礙之一就是如何處理控制其行為的命令行參數(shù)。這包括從命令行傳遞給您程序 個(gè)整數(shù)計(jì)數(shù)(通常名為argc)和一個(gè)指向字符串的指針數(shù)組(通常名為argv).可以采用兩種實(shí)質(zhì)一樣的方式 數(shù),如清單1中所示。清單1.聲明main()函數(shù)的兩種方式int main( int argc, char *argv); int ma

5、in( int argc, char *argv );第一種方式使用的是指向char指針數(shù)組,現(xiàn)在似乎很流行這種方式,比第二種方式(其指針指向多個(gè)指向 楚一些。由于某些原因,我使用第二種方式的時(shí)間更多一些,這可能源于我在高中時(shí)艱難學(xué)習(xí)C指針的經(jīng)歷。 的,這兩種方法都是一樣的,因此可以使用其中您自己最喜歡的方式。當(dāng)C運(yùn)行時(shí)庫的程序啟動(dòng)代碼調(diào)用您的main()時(shí),已經(jīng)對(duì)命令行進(jìn)行了處理。argc參數(shù)包含參數(shù)的計(jì)數(shù) 向這些參數(shù)的指針數(shù)組。對(duì)于C運(yùn)行時(shí)庫,arguments是程序的名稱,程序名后的任何內(nèi)容都應(yīng)該使用空格 例如,如果使用參數(shù)-v bar 運(yùn)行一個(gè)名為foo程序,您的argc將設(shè)置為4,

6、argv的設(shè)所示。清單2. argv的內(nèi)容argv0 - fooargv1 - -vargv2 - barargv3 - HYPERLINK 一個(gè)程序僅有一組命令行參數(shù),因此我要將此信息存儲(chǔ)在記錄選項(xiàng)和設(shè)置的全局結(jié)構(gòu)中。對(duì)程序有意義的要跟 錄到此結(jié)構(gòu)中,我將使用結(jié)構(gòu)來幫助減少全局變量的數(shù)量。正如我在網(wǎng)絡(luò)服務(wù)設(shè)計(jì)文章(請(qǐng)參閱參考資料)所: 不適合用于線程化編程中,因此要謹(jǐn)慎使用。示例代碼將演示一個(gè)假想的doc2html程序的命令行處理。該doc2html程序?qū)⒛撤N類型的文檔轉(zhuǎn)換為HTM1 命令行選項(xiàng)控制。它支持以下選項(xiàng):-I不創(chuàng)建關(guān)鍵字索引。-l lang轉(zhuǎn)換為使用語言代碼lang指定的語言。-

7、o outfiie.html將經(jīng)過轉(zhuǎn)換的文檔寫入到outfile.html,而不是打印到標(biāo)準(zhǔn)輸出。-V進(jìn)行轉(zhuǎn)換時(shí)提供詳細(xì)信息;可以多次指定,以提高診斷級(jí)別。將使用其他文件名稱來作為輸入文檔。您還將支持-h和-?,以打印幫助消息來提示各個(gè)選項(xiàng)的用途。簡單命令行處理:getopt()getopt()函數(shù)位于unistd.h系統(tǒng)頭文件中,其原型如清單3中所示:清單3. getopt()原型int getopt( int argc, char *const argv, const char *optstring );給定了命令參數(shù)的數(shù)量(argc)、指向這些參數(shù)的數(shù)組(argv)和選項(xiàng)字符串(opts

8、tring)后,getopt(): 設(shè)置一些全局變量。使用相同的參數(shù)再次調(diào)用該函數(shù)時(shí),它將返回下一個(gè)選項(xiàng),并設(shè)置相應(yīng)的全局變量。如果 將返回-1,此任務(wù)就完成了。getopt()所設(shè)置的全局變量包括:optarg指向當(dāng)前選項(xiàng)參數(shù)(如果有)的指針。optind再次調(diào)用getopt()時(shí)的下一個(gè)argv指針的索引。optopt最后一個(gè)已知選項(xiàng)。對(duì)于每個(gè)選項(xiàng),選項(xiàng)字符串(optstring)中都包含一個(gè)對(duì)應(yīng)的字符。具有參數(shù)的選項(xiàng)(如示例中的-l和- 個(gè):字符。示例所使用的optstring為Il:o:vh?(前面提到,還要支持最后兩個(gè)用于打印程序的使用方 可以重復(fù)調(diào)用getopt(),直到其返回-1

9、為止;任何剩下的命令行參數(shù)通常視為文件名或程序相應(yīng)的其他F getopt()的使用讓我們對(duì)getopt_demo項(xiàng)目的代碼進(jìn)行一下深入分析;為了方便起見,我在此處將此代碼拆分為多個(gè)部分, 碼部分獲得完整的代碼(請(qǐng)參見下載)。在清單4中,可以看到系統(tǒng)演示程序所使用的系統(tǒng)頭文件;標(biāo)準(zhǔn)stdio.h提供標(biāo)準(zhǔn)I/O函數(shù)原型,stdli EXIT_SUCCESS 和 EXIT_FAILURE,unistd.h 提供 getopt()。清單4.系統(tǒng)頭文件#include #include #include 清單5顯示了我所創(chuàng)建的globalArgs結(jié)構(gòu),用于以合理的方式存儲(chǔ)命令行選項(xiàng)。由于這是個(gè)全局變量,

10、3 都可以訪問這些變量,以確定是否創(chuàng)建關(guān)鍵字索引、生成何種語言等等事項(xiàng)。最好讓main()函數(shù)外的代碼將 只讀存儲(chǔ)區(qū),因?yàn)槌绦虻娜魏尾糠侄伎梢砸蕾囉谄鋬?nèi)容。每個(gè)命令行選擇都有一個(gè)對(duì)應(yīng)的選項(xiàng),而其他變量用于存儲(chǔ)輸出文件名、指向輸入文件列表的指針和輸入文件 清單5.全局參數(shù)存儲(chǔ)和選項(xiàng)字符串/* -I option */* -l option */* -o option */* -v option */* input files */* # of input files */struct globalArgs_t int noIndex; char *langCode;const char *out

11、FileName;file *outFile;int verbosity;char *inputFiles;int numinputFiles; globalArgs;static const char *optString = Il:o:vh?;選項(xiàng)字符串optString告知getopt()可以處理哪個(gè)選項(xiàng)以及哪個(gè)選項(xiàng)需要參數(shù)。如果在處期間遇到了其, 顯示一個(gè)錯(cuò)誤消息,程序?qū)⒃陲@示了使用方法消息后退出。下面的清單6包含一些從main()引用的用法消息函數(shù)和文檔轉(zhuǎn)換函數(shù)的小存根。可以對(duì)這些存根進(jìn)行自由 的目的。清單6.存根void display_usage( void )puts( doc

12、2html - convert documents to HTML);/* . */exit( EXIT_FAILURE );void convert_document( void )/* . */最后,如清單7中所示,在main()函數(shù)中使用此結(jié)構(gòu)。和優(yōu)秀的開發(fā)人員一樣,您需要首先初始化glob 開始處理命令行參數(shù)。在您的程序中,可以借此設(shè)置在一定情況下合理的缺省值,以便在以后有更合適的缺省 調(diào)整。清單7.初始化int main( int argc, char *argv) int opt = 0;/* Initialize globalArgs before we get to work.

13、 */ globalArgs.noindex = 0;/* false */globalArgs.langCode = null; globalArgs.outFileName = null; globalArgs.outFile = null; globalArgs.verbosity = 0;globalArgs.inputFiles = null; globalArgs.numinputFiles = 0;清單8中的while循環(huán)和switch語句是用于本程序的命令行處理的代碼部分。只要getopt()發(fā)現(xiàn)選: 定找到的是哪個(gè)選項(xiàng),將能在globalArgs結(jié)構(gòu)中看到具體情況。當(dāng)geto

14、pt()最終返回1時(shí),就完成 的都是您的輸入文件了。清單 8.使用 getopt() 處理 argc/argvopt = getopt( argc, argv, optString );while( opt != -1 ) switch( opt ) case i:globalArgs.noindex = 1; /* true */ break;case l:globalArgs.langCode = optarg; break;case o:globalArgs.outFileName = optarg; break;case v:globalArgs.verbosity+;break;ca

15、se h:/* fall-through is intentional */case ?:display_usage();break;default:/* You wont actually get here. */ break;opt = getopt( argc, argv, optString );globalArgs.inputFiles = argv + optind;globalArgs.numInputFiles = argc - optind;既然已經(jīng)完成了參數(shù)和選項(xiàng)的收集工作,接下來就可以執(zhí)行程序所設(shè)計(jì)的任何功能(在本例中是進(jìn)行文檔轉(zhuǎn)換)清單9.開始工作|convert_do

16、cument();return exit_success好,工作完成,非常漂亮?,F(xiàn)在就可以不再往下讀了。不過,如果您希望程序符合90年代末期的標(biāo)準(zhǔn)并支持 行的長選項(xiàng),則請(qǐng)繼續(xù)關(guān)注下面的內(nèi)容。復(fù)雜命令行處理:getopt_long()在20世紀(jì)90年代(如瘋有記錯(cuò)的話),UNIX應(yīng)用程序開始支持長選項(xiàng),即一對(duì)短橫線(而不是普通短 橫線)、一個(gè)描述性選項(xiàng)名稱還可以包含一個(gè)使用等號(hào)連接到選項(xiàng)的參數(shù)。幸運(yùn)的是,可以通過使用getopt_long()向程序添加長選項(xiàng)支持。您可能已經(jīng)猜到了,getopt_long(); 選項(xiàng)的getopt()版本。getopt_long()函數(shù)還接受其他參數(shù),其中一個(gè)是指

17、向struct option對(duì)象數(shù)組的指針。此結(jié)構(gòu)相當(dāng)直接清單10. getopt long()的選項(xiàng)I struct option char *name;int has_arg int *flag;int val;name成員是指向長選項(xiàng)名稱(帶兩個(gè)短橫線)的指針。has_arg成員設(shè)置為no_argument、optional. required_argument (均在getopt.h中定義)之一,以指示選項(xiàng)是否具有參數(shù)。如果flag成員未設(shè)置 遇到此選項(xiàng)時(shí),會(huì)使用val成員的值填充它所指向的int值。如果flag成員為NULL,在getopt_long 返回val中的值;通過將val設(shè)

18、置為選項(xiàng)的short參數(shù),可以在不添加任何其他代碼的情況下使用get( while loop和switch的現(xiàn)有g(shù)etopt()將自動(dòng)處理此選項(xiàng)。這已經(jīng)變得更為靈活了,因?yàn)楦鱾€(gè)選項(xiàng)現(xiàn)在可以具有可選參數(shù)了。更重要的是,僅需要進(jìn)行很少的工作,就可 中。讓我們看看如何使用getopt_long()來對(duì)示例程序進(jìn)行更改(getopt_long_demo項(xiàng)目可從下載部分獲得) 使用 getopt_long()由于getopt_long_demo幾乎與剛剛討論的getopt_demo代碼一樣,因此我將僅對(duì)更改的代碼進(jìn)行說明。由 靈活性,因此還將添加對(duì)-randomize選項(xiàng)(沒有對(duì)應(yīng)的短選項(xiàng))的支持。ge

19、topt_long()函數(shù)在getopt,h頭文件(而非unistd.h)中,因此將需要將該頭文件包含進(jìn)來(請(qǐng)參 含了 string.h,因?yàn)閷⑸院笫褂胹trcmp()來幫助確定處理的是哪個(gè)長參數(shù)。清單11.其他頭文件#include #include 您已經(jīng)為-randomize選項(xiàng)在globalArgs中添加了一個(gè)標(biāo)志(請(qǐng)參見清單12),并創(chuàng)建了 longOpts 序支持的長選項(xiàng)的信息。除了 -randomize夕卜,所有的參數(shù)都與現(xiàn)有短選項(xiàng)對(duì)應(yīng)(例如,-no-index等 項(xiàng)結(jié)構(gòu)中包含其短選項(xiàng)等效項(xiàng),可以在不向程序添加任何其他代碼的情況下處理等效的長選項(xiàng)。清單12.擴(kuò)展后的參數(shù)struc

20、t globalArgs_t int noIndex; char *langCode;const char *outFileName;file *outFile;int verbosity;char *inputFiles;int numinputFiles;int randomized; globalArgs;/* -I option */* -l option */* -o option */* -v option */* input files */* # of input files */* -randomize option */static const char *optStrin

21、g = Il:o:vh?;static const struct option longOpts = no-index, no_argument, null, i , language, required_argument, null, l , output, required_argument, null, o , verbose, no_argument, null, v , randomize, no_argument, null, 0 ), help, no_argument, null, h , null, no_argument, null, 0 ) ;清單13將getop()調(diào)用

22、更改為了 getopt_long(),除了 getopt()的參數(shù)外,它還接受longOpts (longIndex)。當(dāng)getopt_long()返回0時(shí),longIndex所指向的整數(shù)將設(shè)置為當(dāng)前找到的長選項(xiàng)的索清單13.新的經(jīng)改進(jìn)的選項(xiàng)處理opt = getopt_long( argc, argv, optString, longOpts, &longindex ); while( opt != -1 ) switch( opt ) case I:globalArgs.noindex = 1; /* true */ break;case l:globalArgs.langCode = o

23、ptarg; break;case o:globalArgs.outFileName = optarg; break;case v:globalArgs.verbosity+; break;case h:/* fall-through is intentional */case ?:display_usage(); break;case 0:/* long option without a short arg */if( strcmp( randomize, longO ) = 0 ) globalArgs.randomized = 1; break;defa

24、ult:/* You wont actually get here. */ break;opt = getopt_long( argc, argv, optString, longOpts, amp;longIndex );我還添加了 0的case,以便處理任何不與現(xiàn)有短選項(xiàng)匹配的長選項(xiàng)。在此例中,只有一個(gè)長選項(xiàng),但代碼仍 確保它是預(yù)期的那個(gè)選項(xiàng)。這樣就全部搞定了;程序現(xiàn)在支持更為詳細(xì)(對(duì)臨時(shí)用戶更加友好)的長選項(xiàng)??偨Y(jié)UNIX用戶始終依賴于命令行參數(shù)來修改程序的行為,特別是那些設(shè)計(jì)作為小工具集合(UNIX外殼環(huán)境)的 具更是如此。程序需要能夠快速處理各個(gè)選項(xiàng)和參數(shù),且要求不會(huì)浪費(fèi)開發(fā)人員的太多時(shí)間。畢竟,幾乎沒有 行參數(shù),開發(fā)人員更應(yīng)該將精力放在程序所實(shí)際進(jìn)行的工作上。getopt()函數(shù)是一個(gè)標(biāo)準(zhǔn)庫調(diào)用,可允許您使用直接的while/switch語句方便地逐個(gè)處理命令行參數(shù)和檢7 的參數(shù))。與其類似的getopt_long()允許在幾乎不進(jìn)行額外工作的情況下處理更具描述性的長選項(xiàng),這非 既然已經(jīng)知道了如何方便地處理命令行選項(xiàng),現(xiàn)在就可以集中精力改進(jìn)您的程序的命令行,可以添加長選項(xiàng)支 想向程序添加額外的命令

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論