Linux中c程序命令行参数解析

在Linux中,较为复杂的C程序命令行参数的解析通常使用getopt, getopt_long以及getopt_long_only来进行,如下所示。

#include 

int getopt(int argc, char *const argv[],
           const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;

#include 

int getopt_long(int argc, char *const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char *const argv[],
                     const char *optstring,
                     const struct option *longopts, int *longindex);

其中getopt仅能用于解析短选项(即以单个-开头接单个字母的选项,例如-a,-b),getopt_long既可以解析短选项也可以解析长选项(以--开头,后接一个单词,例如--mode),getopt_long_only相比getopt_long而言可以匹配不规范的长选项(以单个-开头,后接单词,例如-mode)。

关键数据结构

struct option {
    const char *name;
    int         has_arg;
    int        *flag;
    int         val;
};

程序接收的短选项可以使用字符串语法进行描述,而长选项需要使用option结构体来进行描述。

字段 说明
name 长选项名称
has_arg 是否需要参数,可以设置为
no_argument
required_argument
optional_argument
flag flag0getopt_long扫描到该参数时返回val,否则将flag指向的变量设置为val
val flag所述

API说明

关于API的使用仅介绍getopt_long,通常getopt_long就可以满足需要,其余两个API使用方式也类似。

extern char *optarg;
extern int optind, opterr, optopt;
int getopt_long(int argc, char *const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);
参数 说明
argc main函数的argc参数
argv main函数的argv参数
optstring 描述合法短选项的字符串,字符串中每一个字符表示一个短选项,如果一个字符后紧接一个:则表示该选项需要一个参数,例如ab:cd:表示接收四个合法选项,分别为a, b, c, d,其中bd需要参数。
longopts 描述长选项的数组,见上一小节关键数据结构所述。该数组中最后一项的各个字段需要均为0,表示数组结束(因为这里没有传递数组长度参数)
longindex 当getopt_long扫描到一个匹配的长选项时,该指针指向的值被设置为长选项在longopts数组中的索引
返回值 返回-1表示所有参数已经解析完毕
返回?表示遇到不合法的选项
扫描到短选项时返回短选项(短选项为单个字符(char),因此可以使用int表示)
扫描到长选项时返回值见上一小节关键数据结构所述
全局变量 说明
optarg 描述到需要参数的选项时,该变量设置为选项对应的参数
optind 下一个要处理的参数在argv数组中的索引
opterr opterr设置为0时,getopt_long在遇到不合法选项时不会打印错误;设置为1时,则会打印错误信息(默认为1)
optopt getopt_long在遇到不合法的短选项时将该变量设置为不合法的短选项

getopt_long会调整argv中参数的位置,使得非选项参数均被放到最后边。例如输入参数为-a pos1 -b pos2 -c pos3,其中a,b,c均不接收参数,在解析完参数后,argv中参数变为-a -b -c pos1 pos2 pos3,我们可以使用optind获取pos1的索引位置从而完后后续非选项参数的处理

详细内容参考getopt(3) - Linux manual page (man7.org)

示例

#include 
#include 
#include 

#define REQUIRED_ARGUMENT_NUM 3
int main(int argc, char* argv[]) {
    char* config_filename = NULL;
    char* key_filename = NULL;
    char* plain_addr = NULL;
    char* cipher_addr = NULL;
    int i;
    // 保存getopt_long返回值
    char c;
    
    // long_options的最后一项需要设置为全0表示结束
    static struct option long_options[] = {
            {"config",    required_argument, 0,  0},
            {"plain_addr", required_argument, 0,  1 },
            {"cipher_addr",  required_argument, 0, 2},
            {"keyfile", required_argument, 0, 3},
            {0,  0,  0,  0 }
        };
    while (1) {
        // 扫描到长选项时获取该选项在long_options数组中的索引
        int option_index = 0;
        // 第三个参数用于指定合法的短选项
        c = getopt_long(argc, argv, "hab",
                long_options, &option_index);
        // 返回-1表示所有选项扫描完毕
        if (c == -1)
            break;
		// 处理选项参数值,选项参数值保存在全局变量optarg中,为一个字符串
        switch (c) {
        case 0:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 1:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 2:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 3:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 'a':
            printf("Get option a\n");
        // 未知选项
        case '?':
            break;
        default:
            printf("Unknown return val: %d\n", c);
        }
    }

    // 除了选项,还需要3个位置参数
    if (argc - optind != REQUIRED_ARGUMENT_NUM)  {
        printf("Argumnet error, required %d, get %d\n", REQUIRED_ARGUMENT_NUM, argc - optind);
        return -1;
    }
	
    // 除了选项,打印3个位置参数
    for (i=optind; i < argc; i++) {
        printf("position arg %d, value %s\n", i - optind, argv[i]);
    }

    return 0;
}

你可能感兴趣的:(linux,命令行参数,c语言,Linux)