【Linux函数】命令行参数解析函数

文章目录

  • 前言
  • 版本迭代
  • 参考文档
  • 命令行参数
  • getopt()
  • getopt_long()
  • getopt_long_only()
  • 总结

前言

每个开源代码的main函数中都有一个命令行参数解析函数,今天特意参考各种博客资料总结一下。

版本迭代

时间 版本 版本更新
2024.8.26 V1.0 初始版本

参考文档

1.https://blog.csdn.net/qq_41816308/article/details/132899633

2.https://blog.csdn.net/Tschome/article/details/129132082

命令行参数

命令行参数可以分为两类,一类是短选项,一类是长选项,短选项在参数前加一杠"-“,长选项在参数前连续加两杠”–"。-a,-A,-b都表示短选项,–all,–almost-all, --author都表示长选项。

getopt()

声明

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

描述

用于解析命令行选项。它通过遍历argv数组中的参数,识别选项字符短选项(例如 -a, -b 等),并根据 optstring指定的选项格式返回结果。每次调用getopt返回一个选项字符,直到没有更多选项。

参数

  • argc: 命令行参数的数量。
  • argv: 命令行参数数组。
  • optstring: 指定合法选项的字符串,选项后面可以跟一个冒号(:)表示该选项需要一个参数。

返回值

  • 返回选项字符(例如-a对应a)。
  • 如果没有更多选项,返回-1。
  • 如果遇到无效选项或缺少参数,返回 ? 或 : 。

实例

#include 
#include 

int main(int argc, char *argv[]) 
{
    int opt;
    
    while ((opt = getopt(argc, argv, "ab:c")) != -1) 
	{
        switch (opt)
		{
            case 'a':
                printf("Option a\n");
                break;
            case 'b':
                printf("Option b with value %s\n", optarg);
                break;
            case 'c':
                printf("Option c\n");
                break;
            case '?':
                printf("Unknown option\n");
                break;
        }
    }
    
    return 0;
}

结果

假设命令行输入为:

./program -a -b value -c

输出结果将是:

Option a
Option b with value value
Option c

在此示例中,-a 和 -c不需要参数,-b需要一个参数(value),optarg 用于获取 -b 后面的参数值。如果-a或者-c带了参数也不会从optarg中获取到,他会显示NULL。

case 'a':
//printf("Option a\n");
printf("Option a with value %s\n", optarg);
break;

//结果
Option a with value (null)
Option b with value 20
Option c

getopt_long()

声明

#include 
int getopt_long(int argc, char *const argv[], const char *shortopts, const struct option *longopts, int *longindex);

描述

getopt_long() 是一个扩展的getopt()函数,支持长选项(如 --option)以及短选项(如-o)。

参数

  • argc: 命令行参数的数量。
  • argv: 命令行参数数组。
  • shortopts: 一个字符串,定义所有短选项及其参数要求。
  • longopts: 一个struct option数组,定义所有长选项及其参数要求。数组最后一个元素必须是全零的结构体。(长选项结构体)
  • longindex: 可选参数,用于存储匹配的长选项的索引。如果不需要,可以设置为NULL。
struct option
{
     const char *name;
     int         has_arg;
     int        *flag;
     int         val;
};
eg:
 static struct option longOpts[] = {
      { "daemon", no_argument, NULL, 'D' },
      { "dir", required_argument, NULL, 'd' },
      { "out", required_argument, NULL, 'o' },
      { "log", required_argument, NULL, 'l' },
      { "split", required_argument, NULL, 's' },
      { "http-proxy", required_argument, &lopt, 1 },
      { "http-user", required_argument, &lopt, 2 },
      { "http-passwd", required_argument, &lopt, 3 },
      { "http-proxy-user", required_argument, &lopt, 4 },
      { "http-proxy-passwd", required_argument, &lopt, 5 },
      { "http-auth-scheme", required_argument, &lopt, 6 },
      { "version", no_argument, NULL, 'v' },
      { "help", no_argument, NULL, 'h' },
      { 0, 0, 0, 0 }
    };

/*
	name:表示选项的名称,比如daemon,dir,out等。
	has_arg:表示选项后面是否携带参数。该参数有三个不同值,如下:
		no_argument(或者是0)时 ——参数后面不跟参数值,eg: --version,--help
		required_argument(或者是1)时 ——参数输入格式为:–参数 值 或者 --参数=值。eg:--dir=home 或者 --dir home
		optional_argument(或者是2)时 ——参数输入格式只能为:-–参数=值
	flag:空或者非空。
		如果参数为空NULL,那么当选中某个长选项的时候,getopt_long将返回val值。
		如果参数不为空,那么当选中某个长选项的时候,getopt_long将返回0,并且将flag指针参数指向val值。
	val:表示指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值val。
*/

全局变量

  • optarg:表示当前选项对应的参数值。

  • optind:表示的是下一个将被处理到的参数在argv中的下标值。

  • opterr:如果opterr = 0,在getopt、getopt_long、getopt_long_only遇到错误将不会输出错误信息到标准输出流。opterr在非0时,向屏幕输出错误。

  • optopt:表示没有被未标识的选项。

返回值

  • 返回选项字符(对于短选项)或longopts中定义的长选项的val字段。
  • 如果遇到未知选项或选项格式不正确,则返回?。
  • 当所有选项被处理完或达到命令行参数数组的末尾时,返回-1。

实例1

#include 
#include 
#include 

int main(int argc, char *argv[]) {
    int opt;
    int option_index = 0;

    static struct option long_options[] = {
        {"add",    no_argument,       0, 'a'},
        {"append", no_argument,       0, 'b'},
        {"delete", required_argument, 0, 'd'},
        {"create", required_argument, 0, 'c'},
        {"verbose", no_argument,      0, 'v'},
        {"version", no_argument,      0, 'V'},
        {0, 0, 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "ab:d:c:uvV", long_options, &option_index)) != -1) {
        switch (opt) {
            case 'a':
                printf("Option a\n");
                break;
            case 'b':
                printf("Option b\n");
                break;
            case 'c':
                printf("Option c with argument '%s'\n", optarg);
                break;
            case 'd':
                printf("Option d with argument '%s'\n", optarg);
                break;
            case 'v':
                printf("Option v\n");
                break;
            case 'V':
                printf("Option V\n");
                break;
            case '?':
                break;
            default:
                abort();
        }
    }

    return 0;
}

结果1

运行上面的代码,例如:

./test --add --create file.txt -d 123 --delete 567

会输出:

Option a
Option c with argument 'file.txt'
Option d with argument '123'
Option d with argument '567'

在实例中,–delete和-d是等价的。遇到短选项他会直接到switch中找相应的case,如果是长选项他会先去long_options结构体数组中找对应的第四个参数,如果在去switch中找相应的case。

实例2

本案例主要是讲解longOpts中第三个参数lopt这个参数的作用和option_index的用法。

longOpts中的第三个参数如果是NULL,则第四个参数要使用单个字符;如果给了一个int型的地址,第四个参数要用数字。

#include 
#include 
#include 

int lopt; // 用于接收选项标志的变量

int main(int argc, char *argv[]) {
    int option_index = 0;
    int c;

    // 定义长选项
    static struct option longOpts[] = {
        { "daemon", no_argument, NULL, 'D' },
        { "dir", required_argument, NULL, 'd' },
        { "out", required_argument, NULL, 'o' },
        { "log", required_argument, NULL, 'l' },
        { "split", required_argument, NULL, 's' },
        { "http-proxy", required_argument, &lopt, 1 },
        { "http-user", required_argument, &lopt, 2 },
        { "http-passwd", required_argument, &lopt, 3 },
        { "http-proxy-user", required_argument, &lopt, 4 },
        { "http-proxy-passwd", required_argument, &lopt, 5 },
        { "http-auth-scheme", required_argument, &lopt, 6 },
        { "version", no_argument, NULL, 'v' },
        { "help", no_argument, NULL, 'h' },
        { 0, 0, 0, 0 }
    };

    // 解析命令行选项
    while ((c = getopt_long(argc, argv, "D:d:o:l:s:vh", longOpts, &option_index)) != -1) {
        printf("Option Index: %d\n", option_index);
        switch (c) {
            case 'D':
                printf("Daemon mode enabled\n");
                break;
            case 'd':
                printf("Directory: %s\n", optarg);
                break;
            case 'o':
                printf("Output file: %s\n", optarg);
                break;
            case 'l':
                printf("Log file: %s\n", optarg);
                break;
            case 's':
                printf("Split size: %s\n", optarg);
                break;
            case 'v':
                printf("Version 1.0\n");
                break;
            case 'h':
                printf("Help: Usage: [options]\n");
                break;
            case 1: // http-proxy
                printf("HTTP Proxy: %s\n", optarg);
                break;
            case 2: // http-user
                printf("HTTP User: %s\n", optarg);
                break;
            case 3: // http-passwd
                printf("HTTP Password: %s\n", optarg);
                break;
            case 4: // http-proxy-user
                printf("HTTP Proxy User: %s\n", optarg);
                break;
            case 5: // http-proxy-passwd
                printf("HTTP Proxy Password: %s\n", optarg);
                break;
            case 6: // http-auth-scheme
                printf("HTTP Auth Scheme: %s\n", optarg);
                break;
            case '?':
                // 错误处理,未知选项
                fprintf(stderr, "Unknown option or missing argument\n");
                break;
            default:
                fprintf(stderr, "Unexpected option\n");
                break;
        }
    }

    return 0;
}

结果2

 ./myprogram --daemon --dir /tmp --out output.txt --log error.log --http-proxy http://proxy.example.com --http-user user --http-passwd passwd --version


Option Index: 0
Daemon mode enabled
Option Index: 1
Directory: /tmp
Option Index: 2
Output file: output.txt
Option Index: 3
Log file: error.log
Option Index: 5
Unexpected option
Option Index: 6
Unexpected option
Option Index: 7
Unexpected option
Option Index: 11
Version 1.0

getopt_long_only()

声明

#include 
int getopt_long_only(int argc, char *const argv[], const char *shortopts,
                     const struct option *longopts, int *longindex);

描述

getopt_long_only()函数用于解析命令行选项,支持长选项的解析,并且不处理短选项。

参数

  • argc: 命令行参数的个数,即传递给main函数的argc。
  • argv: 命令行参数数组,即传递给main函数的argv。
  • shortopts: 一个字符串,定义了短选项。如果不处理短选项,此参数可以是NULL。
  • longopts: 一个struct option类型的数组,用于定义长选项。数组的最后一个元素必须是{0, 0, 0, 0}。
  • longindex: 指向整数的指针,用于存储长选项的索引。如果不需要,可以将其设置为NULL。

返回值

  • ?: 遇到未知的选项。
  • :: 短选项缺少必要的参数。
  • 0: 成功解析了一个长选项,并返回与该长选项对应的字符值。
  • -1: 解析完成或出错。

实例

#include 
#include 

int main(int argc, char *argv[]) {
    int opt;
    int option_index = 0;

    static struct option long_options[] = {
        {"add",    no_argument,       0, 0},
        {"create", required_argument, 0, 0},
        {"verbose", no_argument,      0, 0},
        {"version", no_argument,      0, 0},
        {0, 0, 0, 0}
    };

    while ((opt = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) 
	{
        switch (opt) 
		{
            case 0:
                printf("Long option %s\n", long_options[option_index].name);
                if (long_options[option_index].has_arg == required_argument) 
				{
                    printf("With argument: %s\n", optarg);
                }
                break;
            default:
                fprintf(stderr, "Usage: %s [--add] [--create arg] [--verbose] [--version]\n", argv[0]);
                return 1;
        }
    }

    return 0;
}

结果

运行上述程序时,如果传递以下命令行参数:

./program --add --create example --verbose --version

输出将是:

Long option add
Long option create
With argument: example
Long option verbose
Long option version

总结

getopt():只支持短选项。

getopt_long():支持短选项和长选项。

getopt_long_only():只支持长选项。

如果有错误请帮忙指出,谢谢!

你可能感兴趣的:(嵌入式Linux,c语言,linux)