每一天你都在使用大量的命令行程序,是不是感覺(jué)那些命令行參數用起來(lái)比較方便,他們都是使用getopt來(lái)實(shí)現的。
在Linux下使用getopt寫(xiě)程序是一種比較cool的事情,下面來(lái)簡(jiǎn)單的介紹一下getopt的使用。
=== getopt使用 ===
在討論參數處理之前,我們先明確兩個(gè)概念:選項、選項參數
gcc -g -o test test.c
我們經(jīng)常使用上面的命令來(lái)編譯程序,這里g和o就是選項,其中test就是o的選項參數
下面我們來(lái)看一下getopt:
首先是函數聲明:
#include <unistd.h>
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;
int getopt(int argc, char * const *argv, const char *optstring);
直接看一個(gè)例子:
/* getopt.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int aflag=0, bflag=0, cflag=0;
int ch;
while ((ch = getopt(argc, argv, "ab:c")) != -1)
{
printf("optind: %d\n", optind);
switch (ch) {
case 'a':
printf("HAVE option: -a\n");
aflag = 1;
break;
case 'b':
printf("HAVE option: -b\n");
bflag = 1;
printf("The argument of -b is %s\n", optarg);
break;
case 'c':
printf("HAVE option: -c");
cflag = 1;
break;
case '?':
printf("Unknown option: %c\n",(char)optopt);
break;
}
}
}
通過(guò)上面的例子,大家應該可以照貓畫(huà)虎,就可以在自己的程序中使用getopt函數了。
getopt()每調用一次返回一個(gè)選項。
argc 和 argv 很顯然就是 main 函數的兩個(gè)參數。
字符串 optstring 可以包含下列元素:?jiǎn)蝹€(gè)字符,字符后面接一個(gè)冒號說(shuō)明后面跟隨一個(gè)選項參數,字符后面接兩個(gè)冒號說(shuō)明后面跟隨一個(gè)可有可無(wú)的選項參數。例如,一個(gè)選項字符 "x" 表示選項 "-x" ,選項字符 "x:" 表示選項和其參數 "-x argument",選項字符 "x::" 表示選項 x 的參數是可選的(“::” 是 GNU 增加的,不一定在所有的UNIX 系統下都可以使用)。
getopt()的返回后,如果有選項參數的話(huà) optarg 指向選項參數,并且變量 optind 包含下一個(gè) argv 參數作為對 getopt() 下一次調用的索引。變量 optopt 保存最后一個(gè)由 getopt() 返回的已知的選項。
當參數列已經(jīng)到結尾時(shí)getopt()函數返回-1,當遇到一個(gè)未知的選項時(shí) getopt 返回'?'。參數列中選項的解釋可能會(huì )被'--'取消,由于它引起 getopt()給參數處理發(fā)送結束信號并返回-1。
很多時(shí)候,我們不希望輸出任何錯誤信息,或更希望輸出自己定義的錯誤信息??梢圆捎靡韵聝煞N方法來(lái)更改getopt()函數的出錯信息輸出行為:
在調用getopt()之前,將opterr設置為0,這樣就可以在getopt()函數發(fā)現錯誤的時(shí)候強制它不輸出任何消息。
如果optstring參數的第一個(gè)字符是冒號,那么getopt()函數就會(huì )保持沉默,并根據錯誤情況返回不同字符,如下:
“無(wú)效選項” ―― getopt()返回'?',并且optopt包含了無(wú)效選項字符(這是正常的行為)。
“缺少選項參數” ―― getopt()返回':',如果optstring的第一個(gè)字符不是冒號,那么getopt()返回'?',這會(huì )使得這種情況不能與無(wú)效選項的情況區分開(kāi)。
例如optstring為:a:b::c,表示a帶一個(gè)參數,b可選,c不帶參數
如果輸入d,“無(wú)效選項“,getopt返回'?'
如果輸入的a忘記帶參數,“缺少選項參數”,getopt應返':' ;如果不再optstring的第一個(gè)字符不是':'的話(huà),那么將會(huì )把這個(gè)錯當成"無(wú)效參數",從而getopt返回'?';從而無(wú)法區別錯誤類(lèi)型
比如:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -d -b foo
optind: 2
HAVE option: -a
./getopt: invalid option -- d
optind: 3
Unknown option: d
optind: 5
HAVE option: -b
The argument of -b is foo
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -- -c -b foo
optind: 2
HAVE option: -a
getopt 的源代碼在下面,getopt 將只會(huì )解釋到 -a。
變量opterr和optind都被初始化為1。如果想要略去命令行的前幾個(gè)參數,可以在調用getopt()前將optind設成其他值。
如果不希望getopt()輸出出錯信息,將全域變量 opterr 設為 0 即可。
是不是使用比較簡(jiǎn)單啊!
=== getopt_long使用 ===
我敢說(shuō),幾乎每個(gè)人在接觸到一個(gè)新的命令的時(shí)候,第一件干的事情就是 cmd -h 或者是 cmd --help,-h我們都知道是使用getopt來(lái)實(shí)現的,那么--help是怎么實(shí)現的呢?那就是getopt_long了,他可以支持長(cháng)參數
先看一個(gè)例子程序:
#include <stdio.h>
#include <getopt.h>
int do_name, do_gf_name;
char *l_opt_arg;
static const char *shortopts = "l:ng";
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{0, 0, 0, 0},
};
int main (int argc, char *argv[])
{
int c;
while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
{
switch (c)
{
case 'n':
printf ("My name is LYR.\n");
break;
case 'g':
printf ("Her name is BX.\n");
break;
case 'l':
l_opt_arg = optarg;
printf ("Our love is %s!\n", l_opt_arg);
break;
}
}
return 0;
}
代碼中我們使用getopt_long來(lái)實(shí)現長(cháng)選項的解析,其中我們使用了一個(gè)結構體struct options的數組,struct options longopt[].
struct options的定義如下:
struct option{
const char *name;
int has_arg;
int *flag;
int val;
};
對結構中的各元素解釋如下:
const char *name
這是選項名,前面沒(méi)有短橫線(xiàn)。譬如"help"、"verbose"之類(lèi)。
int has_arg
描述了選項是否有選項參數。如果有,是哪種類(lèi)型的參數,此時(shí),它的值一定是下表中的一個(gè)。
符號常量 數值 含義
no_argument 0 選項沒(méi)有參數
required_argument 1 選項需要參數
optional_argument 2 選項參數可選
int *flag
如果這個(gè)指針為NULL,那么 getopt_long()返回該結構val字段中的數值。如果該指針不為NULL,getopt_long()會(huì )使得它所指向的變量中填入val字段中的數值,并且getopt_long()返回0。如果flag不是NULL,但未發(fā)現長(cháng)選項,那么它所指向的變量的數值不變。
int val
這個(gè)值是發(fā)現了長(cháng)選項時(shí)的返回值,或者flag不是NULL時(shí)載入*flag中的值。典型情況下,若flag不是NULL,那么val是個(gè)真/假值,譬如1或0;另一方面,如果flag是NULL,那么 val通常是字符常量,若長(cháng)選項與短選項一致,那么該字符常量應該與optstring中出現的這個(gè)選項的參數相同。
每個(gè)長(cháng)選項在長(cháng)選項表中都有一個(gè)單獨條目,該條目里需要填入正確的數值。數組中最后的元素的值應該全是0。數組不需要排序,getopt_long()會(huì )進(jìn)行線(xiàn)性搜索。但是,根據長(cháng)名字來(lái)排序會(huì )使程序員讀起來(lái)更容易。
下面,我們看一下程序中的這個(gè)結構:
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{0, 0, 0, 0},
};
結構說(shuō)明了三個(gè)常選項,name、gf_name、love三個(gè)選項,其中love需要選項;它們分別對應的短選項是n、g、l。
注意:上面結構體數組中的結構體的第三個(gè)參數flag都為NULL.
程序運行結果:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --name
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -n
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -l me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --love me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$
=== Reference ===
GNU提供的getopt()函數的特點(diǎn)
http://blog.csdn.net/realduke2000/archive/2007/10/05/1812126.aspx
使用 getopt() 進(jìn)行命令行處理
http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html
=== Questions ===
1、如何在getopt中指定可選參數
2、能否實(shí)現使用一個(gè)選項帶多個(gè)參數,例如 scanner -i 1.1.1.1 2.2.2.2 3.3.3.3
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。