天天看點

Linux下解析指令行的标準形參(getopt)

一、前言

在Linux下開發時,指令行的使用是必不可少的,經常會在指令行運作各種指令,啟動服務,啟動應用程式,檢視函數用法等等;運作這些指令時都會傳入一些參數,比如:

$ ./c_app 127.0.0.1 8888 小明
$ man printf           

這些指令行參數解析,Linux提供了一套函數,可以很友善的解析傳入的各種參數資訊。

這篇文章就介紹如何使用Linux提供的解析函數,完成指令的行的參數解析。

函數原型如下:

#include <unistd.h>
#include <getopt.h>

這3個是全局變量
extern char *optarg;
extern int optind, opterr, optopt;
功能介紹:
optarg——指向目前選項參數(如果有)的指針。  比如: cp 123.c 888/ -fv 、 gcc 123.c -o app
optind——再次調用 getopt() 時的下一個 argv 指針的索引。
optopt——最後一個已知選項。

int getopt(int argc, char * const argv[],const char *optstring);
函數功能: 解析短選項形參. 隻能解析單個字元.

函數參數:
int argc   就是main函數傳入的argc 
char * const argv[]  就是main函數傳入的argv
const char *optstring  将要解析的選項形參格式.
比如: "a:b:c:v"    字母後面跟着冒号就表示該選項形參必須傳遞參數.
傳入形參的時候: a.out -a 666 -b 777 -c 888 -v

傳回值:
解析成功就傳回目前解析的選項形參的字元. 并且會給全局變量指派. optarg這個指針就會指向該選項形參後面的資料位址.
如果失敗就傳回-1   解析錯誤會傳回? 

int getopt_long(int argc, char * const argv[],
         const char *optstring,
         const struct option *longopts, int *longindex);
函數功能:解析長選項形參.
struct option {
   const char *name;   表示要解析的長選項字元串  --abc
   int         has_arg;   0表示不需要參數 1表示必須要 2表示可選
   int        *flag;     一般NULL
   int         val;      當解析到正确的長選項形參的時傳回的字元  k
};


int getopt_long_only(int argc, char * const argv[],
         const char *optstring,
         const struct option *longopts, int *longindex);
函數功能:同時支援解析長選項形參和短選項形參.           

二、案例代碼

2.1 解析指令行的短選項形參

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>

int main(int argc,char **argv)
{
    int c;
    while(1)
    {
        //解析傳入的選項參數   ./a.out -a 123 -b 456 -c 789 -v
        c=getopt(argc,argv,"a:b:c:v?");
        if(c==-1)break;
        switch(c)
        {
        case 'a':
            printf("目前的選項形參:a,值:%s\n",optarg);
            break;
        case 'b':
            printf("目前的選項形參:b,值:%s\n",optarg);
            break;
        case 'c':
            printf("目前的選項形參:c,值:%s\n",optarg);
            break;
        case 'v':
            printf("目前版本:1.2.3\n");
            break;
        case '?':
            printf("用法:./a.out [-a 123 -b 456 -c 789 -v] \n");
            break;   
        default:
            break;
        }
    }
    return 0;
}

[wbyq@wbyq linux_c]$ ./a.out -a 123 -b 67 -c 999
目前的選項形參:a,值:123
目前的選項形參:b,值:67
目前的選項形參:c,值:999
[wbyq@wbyq linux_c]$ ./a.out -a
./a.out: option requires an argument -- 'a'
用法:./a.out [-a 123 -b 456 -c 789 -v] 
[wbyq@wbyq linux_c]$ ./a.out -?
用法:./a.out [-a 123 -b 456 -c 789 -v] 
[wbyq@wbyq linux_c]$ ./a.out -v
目前版本:1.2.3
[wbyq@wbyq linux_c]$ 
           

2.2 解析指令行的長選項形參

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>

struct option opt_list[]=
{
    {"a123",1,NULL,'a'},
    {"b123",1,NULL,'b'},
    {"c123",1,NULL,'c'},
    {"help",0,NULL,'?'},
};

int main(int argc,char **argv)
{
    int c;
    while(1)
    {
        //解析傳入的選項參數   ./a.out -a 123 -b 456 -c 789 -v
        c=getopt_long(argc,argv,"a:b:c:v?",opt_list,NULL);
        if(c==-1)break;
        switch(c)
        {
        case 'a':
            printf("目前的選項形參:a,值:%s\n",optarg);
            break;
        case 'b':
            printf("目前的選項形參:b,值:%s\n",optarg);
            break;
        case 'c':
            printf("目前的選項形參:c,值:%s\n",optarg);
            break;
        case 'v':
            printf("目前版本:1.2.3\n");
            break;
        case '?':
            printf("用法:./a.out [-a 123 -b 456 -c 789 -v] \n");
            break;   
        default:
            break;
        }
    }
    return 0;
}

[wbyq@wbyq linux_c]$ ./a.out -a 12345
目前的選項形參:a,值:12345
[wbyq@wbyq linux_c]$ ./a.out --a123 12345
目前的選項形參:a,值:12345
[wbyq@wbyq linux_c]$ ./a.out -?
用法:./a.out [-a 123 -b 456 -c 789 -v] 
[wbyq@wbyq linux_c]$ ./a.out --help
用法:./a.out [-a 123 -b 456 -c 789 -v] 
[wbyq@wbyq linux_c]$ 
           

2.3 解析複雜的指令行選項形參

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>

struct option opt_list[]=
{
    {"a123",1,NULL,'a'},
    {"b123",1,NULL,'b'},
    {"c123",1,NULL,'c'},
    {"help",0,NULL,'?'},
};

int main(int argc,char **argv)
{
    int c;
    while(1)
    {
        //解析傳入的選項參數   ./a.out -a 123 -b 456 -c 789 -v
        c=getopt_long_only(argc,argv,"a:b:c:v?",opt_list,NULL);
        if(c==-1)break;
        switch(c)
        {
        case 'a':
            printf("目前的選項形參:a,值:%s\n",optarg);
            break;
        case 'b':
            printf("目前的選項形參:b,值:%s\n",optarg);
            break;
        case 'c':
            printf("目前的選項形參:c,值:%s\n",optarg);
            break;
        case 'v':
            printf("目前版本:1.2.3\n");
            break;
        case '?':
            printf("用法:./a.out [-a 123 -b 456 -c 789 -v] \n");
            break;   
        default:
            break;
        }
    }
    return 0;
}

[wbyq@wbyq linux_c]$ ./a.out 
[wbyq@wbyq linux_c]$ ./a.out -a 1234
目前的選項形參:a,值:1234
[wbyq@wbyq linux_c]$ ./a.out -a123 1234
目前的選項形參:a,值:1234
[wbyq@wbyq linux_c]$ ./a.out --a123 1234
目前的選項形參:a,值:1234
           

繼續閱讀