1. 程式人生 > >命令列選項引數解析-getopt函式

命令列選項引數解析-getopt函式

在學習Unix/Linux程式設計實踐教程時,編寫練習一些linux命令,需要對命令列引數進行解析,從而接觸到getopt系列函式:

1. getopt()

2. getopt_long()

3.getopt_long_only()

總結如下:

Parse command-line options

NAME getopt, getopt_long, getopt_long_only, optarg, optind, opterr, optopt -Parse command-line optionsSYNOPSIS#include<unistd.h>int getopt
(int argc,char*const argv[],
constchar*optstring);externchar*optarg;externint optind, opterr, optopt;#include<getopt.h>int getopt_long(int argc,char*const argv[],constchar*optstring,conststruct option *longopts,int*longindex);int getopt_long_only(int argc,char*const argv[],constchar*optstring,const
struct option *longopts,int*longindex);

1. getopt()函式

函式說明

getopt()用來分析命令列引數。引數argc和argv是由main()傳遞的引數個數和內容。引數optstring 則代表欲處理的選項字串。此函式會返回在argv 中下一個的選項字母,此字母會對應引數optstring 中的字母。如果選項字串裡的字母后接著冒號“:”,則表示還有相關的引數,全域變數optarg 即會指向此額外引數。

optopt:如果getopt()找不到符合的引數則會印出錯資訊,並將全域變數optopt設為“?”字元, 
opterr:將全域變數opterr設為0,getopt()不打印出錯資訊 
optarg:

選項的引數指標

短引數的定義

getopt()使用optstring所指的字串作為短引數列表,“lba:d::”這就是一個短參列表,命令列使用時應加上“-”(即“-l”), 

其中短引數在getopt定義裡分為三種:

  • 不帶值的引數,它的定義即是引數本身。
  • 必須帶值的引數,它的定義是在引數本身後面再加一個冒號。
  • 可選值的引數,它的定義是在引數本身後面加兩個冒號 。

在實際呼叫中,’-l -b -a ty -d’, ‘-lb -a ty -ddvalue’, ‘-lb -a ty -ddvalue’都是合法的。這裡需要注意三點:

  • 不帶值的引數可以連寫,-l 和-b,它們可以-l -b分開寫,也可以-lb或-bl連寫。
  • 引數不分先後順序
  • 要注意可選值的引數的值與引數之間不能有空格,必須寫成-ddvalue這樣的格式,如果寫成-d dvalue這樣的格式就會解析錯誤,必選引數的值和引數之間可有空格也可沒有。

optind

變數optind 是argv中要被處理的下一個元素的索引。初始值為1,最大值為optstring中定義的選項個數(有可選(::)引數的算一個;必選(:)引數選項和引數之間沒空格算一個,有空格算兩個)加 1 ,getopt會遍歷argv,每次呼叫後都會讓optind指向下一個option在argv中的索引,每次optind移動多少取決於optstring中的欄位:

  • 遇到”x”,選項不帶引數,optind += 1
  • 遇到“x:”,帶引數的選項,optarg = argv[optind + 1], optind += 2
  • 遇到“x::”,可選引數,屬於#1和#2之一,GNU擴充套件實現。 
    如果一切順利,最後optind應該指向第一個非option引數,如果optind >= argc,說明沒有已經沒有引數了。如果遇到不認識的引數或丟失的引數,另外兩個全域性變數“opterr, optopt”就派上用場了,剩下的就看文件和原始碼吧。

返回值

getopt()每次呼叫會逐次返回命令列傳入的引數。
當沒有引數的最後的一次呼叫時,getopt()將返回-1。
當解析到一個不在optstring裡面的引數,或者一個必選值引數不帶值時,返回'?'。
當optstring是以':'開頭時,缺值引數的情況下會返回':',而不是'?' 。
#include<unistd.h>#include<stdlib.h>#include<stdio.h>int main(int argc,char*argv[]){int flags, opt;int nsecs, tfnd; nsecs =0; tfnd =0; flags =0;while((opt = getopt(argc, argv,"nt:"))!=-1){switch(opt){case'n': flags =1;break;case't': printf("-t %s\n",optarg); tfnd =1;break;default:/* '?' */ fprintf(stderr,"Usage: %s [-t nsecs] [-n] name\n", argv[0]);exit(EXIT_FAILURE);}} printf("flags=%d; tfnd=%d, optind=%d, argc=%d\n", flags, tfnd, optind,argc);if(optind >= argc){ fprintf(stderr,"Expected argument after options\n");exit(EXIT_FAILURE);} printf("argv[optind] name argument = %s\n", argv[optind]);exit(EXIT_SUCCESS);}[[email protected]ty argument]$ ./a.out-tty name-t ty flags=0; tfnd=1, optind=2, argc=3 argv[optind] name argument = name[[email protected] argument]$ ./a.out-t ty name-t ty flags=0; tfnd=1, optind=3, argc=4 argv[optind] name argument = name

2. getopt_long()函式

getopt_long支援長選項的命令列解析,函式中的引數argc和argv通常直接從main()的兩個引數傳遞而來

int getopt_long(int argc,char*const argv[],constchar*optstring,conststruct option *longopts,int*longindex)

getopt_long支援長選項的命令列解析: 
引數argc和argv通常直接從main()的兩個引數傳遞而來。 
optstring是選項引數和getopt函式一致; 
longopts指定長選項,是個結構體指標,結構體如下:

struct option {constchar*name;//name表示的是長引數名int has_argint*flag;//用來決定,getopt_long()的返回值到底是什麼。如果flag是null,則函式會返回與該項option匹配的val值int val;//和flag聯合決定返回值}

has_arg有3個值:

  • no_argument(或者是0),表示該引數後面不跟引數值
  • required_argument(或者是1),表示該引數後面一定要跟個引數值
  • optional_argument(或者是2),表示該引數後面可以跟,也可以不跟引數值

在實際情況中,我們還希望每個長選項都對應一個短選項,此時在option結構中,只需將flag設定為NULL,並將val設定為長選項所對應的短選項字元即可。

例項如下:

#include<stdio.h>/* for printf */#include<stdlib.h>/* for exit */#include<getopt.h>int main(int argc,char**argv){int c;int digit_optind =0;while(1){int this_option_optind = optind ? optind :1;int option_index =0;staticstruct option long_options[]={{"add",1,0,0},{"append",0,0,0},{"delete",1,0,0},{"verbose",0,0,0},{"create",1,0,'c'},{"file",1,0,0},{0,0,0,0}}; c = getopt_long(argc, argv,"abc:d:012", long_options,&option_index);if(c ==-1)break;switch(c){case0: printf("option %s", long_options[option_index].name);if(optarg) printf(" with arg %s", optarg); printf("\n");break;case'0':case'1':