linux下getopt函数的用法

本文深入讲解getopt函数的使用方法,包括如何解析命令行参数、处理选项及其参数,并通过实例展示了getopt函数的工作原理。

getopt()函数用于命令行参数解析。先来看一下main函数的参数。

1,程序参数

   C语言编写的linux程序运行时,是从main函数开始的。main函数的声明如下:

        int main(int argc, char* argv[])

        或者

        int main(int argc, char** argv)

        其中,argc是程序参数的个数,argv是一个代表自身的字符串数组。

 

实验:下面这个程序args.c对其参数进行检查:

<span style="font-size:12px;">#include<stdio.h>
#include<stdlib.h>

int main(int argc, char* argv[])
{
	int arg;
	printf("The number of parameters: argc=%d\n",argc);
	for(arg=0;arg<argc;arg++)
	{
		printf("argv[%d] = %s\n",arg,argv[arg]);
	}
	exit(0);
}</span>

经过编译后,执行

gcc -o args args.c 
./args -a -b host -chello -de -f world

结果如下:

The number of parameters: argc=8
argv[0] = ./args
argv[1] = -a
argv[2] = -b
argv[3] = host
argv[4] = -chello
argv[5] = -de
argv[6] = -f
argv[7] = world

        注:1)参数个数包括程序名本身;  2)argv是一个字符串数组;3)-de选项其实是-d和-e选项组合的,getopt可以识别这种情况的两个选项。

2,getopt函数

 

#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);

以下全局变量配合 getopt 函数。

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

         实际上,在命令行中,可以支持这样命令输入的信息:
               选项:一个选项一般完成不同的功能的操作。
               参数(关联值):在执行相应选项功能操作时输入的信息。
               -a:选项:表示所有。
               -h host_id: h 就是一个选项,但host_id 实际上是一个IP,也就是h 的参数。

      getopt函数将传递给main函数的argc和argv作为参数,同时接受一个选项指定符字符串optstring,该字符告诉getopt哪些选项可用,以及它们是否有关联值(参数)。optstring约定:
    (1)如果就是一个字符,表示某个选项。
    (2)如果一个字符后有1 个冒号,表示选项后面一定要跟一个参数。参数可以紧跟选项或者与选项相隔一个空格。
    (3)如果一个字符后有2 个冒号,表示选项后面可有有一个参数,也可以没有参数,在选项后的参数一定不能跟它以空格间隔。

       例如getopt 函数第三个参数为以下值:
     “ab:c::d::”
      a 后面 没有冒号,是一个选项。
      b 后面有冒号,其后的内容一定要有理解为参数。
      c 和d 双冒号,其后的内容可以有,也可以没有,但如果有,则这个参数一定坚挨着。
      因此如下:      

             ./getopt –a –b host –chello –d

       

        getopt每次先查找‘-’后面的字符,再查看该字符是否是optstring中的选项,以及是否带有正确的参数。对于前面不带‘-’的,且不是作为参数的字符或字符串,则不予理会。

        具体getopt 怎么来解释我们的选项和参数。
        每成功执行一次,将返回当前的一个选项。循环调用getopt就可以依次得到每个选项。

            (1)如果选项有一个关联值,则extern char *optarg指向这个值,否则为NULL;

            (2)如果选项处理完毕,getopt返回-1;

         (3)如果遇到一个无法识别的选项,getopt返回一个问号(?),并把它保存到外部变量optopt中;并把有一个关联值,则extern char *optarg指向这个值,否则为NULL;

         (4)如果一个选项要求有一个关联值(例如例子中的-a),但用户未提供这个值,getopt通常将返回一个问号;但如果

                   ./getopt_exp -a -b 'hi there' -chello world -de -f     (optstring为"a:b:c::de")

                          程序会将-b当成-a的关联值。

                    如果我们将选项字符串的第一个字符设置为冒号,那么getopt将在用户未提供值的情况下返回冒号,而不是?。

                  

                   extern char *optarg;      //如果当前选项后面一定要跟一个参数,且存在参数,则optarg指向该参数;否则为null

                   extern int optind;           //下一个要处理参数的索引
                   extern int optopt;          //用于存储无法识别的选项

                   extern int opterr;           //opterr== 0,不将错误输出的标准错误输出设备。 

 

<span style="font-size:12px;">#include<stdio.h>
#include<unistd.h>

int main(int argc, char* argv[])
{
	int opt,i;
	opterr=0;
	while((opt=getopt(argc,argv,"a:b:c::de"))!=-1)
	{
		switch(opt)
		{
		case 'a':
		printf("option=a,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		case 'b':
		printf("option=b,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		case 'c':
		printf("option=c,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		case 'd':
		printf("option=d,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		case 'e':
		printf("option=e,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		case '?':
		printf("opt=?,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",optarg,optind,optopt,opterr);
		break;
		default:
		printf("default,opt=%c,optarg=%s,optind=%d,optopt=%c,opterr=%d\n",opt,optarg,optind,optopt,opterr);
		break;
		}
		printf("opt=%c\n",opt);
		printf("argv[%d]=%s\n",optind,argv[optind]);
	}
	printf("\nopt=%d,optind=%d\n\n",opt,optind);
	for(;optind<argc;optind++)
		printf("argv[%d]= %s\n",optind,argv[optind]);
	printf("\n");
	for(i=1;i<argc;i++)
		printf("at the end ---- argv[%d]=%s\n",i,argv[i]);
	return 0;
}</span>


编译:gcc -o getopt_exp getopt_exp.c;执行./getopt_exp -a here -b 'hi there' -chello -de come -f world后,结果为

option=a,optarg=here,optind=3,optopt=,opterr=0
opt=a
argv[3]=-b
option=b,optarg=hi there,optind=5,optopt=,opterr=0
opt=b
argv[5]=-chello
option=c,optarg=hello,optind=6,optopt=,opterr=0
opt=c
argv[6]=-de
option=d,optarg=(null),optind=6,optopt=,opterr=0
opt=d
argv[6]=-de
option=e,optarg=(null),optind=7,optopt=,opterr=0
opt=e
argv[7]=come
opt=?,optarg=(null),optind=9,optopt=f,opterr=0
opt=?
argv[9]=world

opt=-1,optind=8

argv[8]= come
argv[9]= world

at the end ---- argv[1]=-a
at the end ---- argv[2]=here
at the end ---- argv[3]=-b
at the end ---- argv[4]=hi there
at the end ---- argv[5]=-chello
at the end ---- argv[6]=-de
at the end ---- argv[7]=-f
at the end ---- argv[8]=come
at the end ---- argv[9]=world

 注:1)getopt能够处理出现在程序参数中任意位置的选项。程序结束后,getopt实际上重组了argv数组,把所有非选项参数集中在一起,从argv[optind]位置开始。如程序结果中的argv[8]。

	for(;optind<argc;optind++)
		printf("argv[%d]= %s\n",optind,argv[optind]);

2)opt,即 getopt函数的返回值,是一个选项,即一个字符,输出时用%c,不能用%s,否则会出现Segmentation fault (core dumped)的错误。

<think>好的,用户想了解Linux C中的getopt函数。我需要先回忆一下这个函数的基本用途和相关知识。getopt是用来解析命令行参数的,这在写命令行工具的时候特别有用。它属于unistd.h头文件,所以需要包含这个头文件。 首先,我应该介绍getopt的基本功能,比如如何处理短选项和参数。比如像-a、-b这样的短选项,以及像-ovalue或者-o value这样的参数。需要说明optstring的格式,比如字母后面跟冒号表示需要参数,两个冒号表示可选参数。 然后,可能需要给出函数原型,说明参数argc、argv和optstring的作用。还要提到全局变量optarg、optind、opterr和optopt,这些变量在解析过程中会被修改,用来存储参数值、索引等。 接下来,可能需要一个示例代码,展示如何使用getopt循环处理选项。例如,一个常见的循环结构,用while和switch来处理每个选项,比如-h显示帮助,-v显示版本,-o带参数等。这样用户能更直观地理解怎么用。 还需要注意一些常见问题和陷阱,比如optstring的正确格式,选项参数的获取方式,以及错误处理。例如,当用户输入未定义的选项时,getopt会返回'?',这时候可能需要提示错误信息。另外,处理完选项后,剩下的非选项参数可以通过argv + optind来访问,这部分也要提醒用户。 另外,可以提到getoptgetopt_long的区别,后者支持长选项,但可能用户暂时只需要了解getopt的基本用法。最后,确保回答结构清晰,分步骤说明,让用户能够逐步理解和应用这个函数。</think>Linux C 中的 `getopt` 函数是用于解析命令行参数的实用工具,属于 `<unistd.h>` 头文件。它帮助程序识别以 `-` 或 `--` 开头的选项(如 `-h`、`-o file`),并支持以下功能: --- ### **核心功能** 1. **短选项解析** - 支持单字符选项(如 `-a`, `-b`) - 支持带参数的选项(如 `-o value` 或 `-ovalue`) - 支持选项分组(如 `-abc` 等效于 `-a -b -c`) 2. **错误处理** - 自动检测未定义的选项 - 处理缺失的参数 --- ### **函数原型** ```c #include <unistd.h> int getopt(int argc, char *const argv[], const char *optstring); ``` - **参数说明**: - `argc`:主函数的参数个数(`main` 函数的 `argc`) - `argv`:主函数的参数字符串数组(`main` 函数的 `argv`) - `optstring`:定义合法选项的字符串(格式见下文) --- ### **optstring 格式** - **单个字符**:合法选项(如 `"a"` 表示 `-a`) - **字符后加 `:`**:选项需要参数(如 `"o:"` 表示 `-o value`) - **字符后加 `::`**:选项参数可选(GNU 扩展,非 POSIX 标准) 示例:`"ab:c::"` 表示: - `-a`(无参数) - `-b value`(必须带参数) - `-c` 或 `-cvalue`(参数可选) --- ### **关键全局变量** - `optarg`:指向当前选项参数的指针(如 `-o file` 中的 `file`) - `optind`:下一个待处理的 `argv` 索引 - `opterr`:是否输出错误信息(默认 `1`,设为 `0` 可禁用) - `optopt`:存储未识别的选项字符 --- ### **使用步骤** 1. **定义选项规则** ```c char *optstring = "hvo:"; // h: 帮助; v: 版本; o: 输出文件(需参数) ``` 2. **循环解析选项** ```c #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int opt; char *output_file = NULL; while ((opt = getopt(argc, argv, "hvo:")) != -1) { switch (opt) { case 'h': printf("Usage: %s [-h] [-v] [-o file]\n", argv[0]); return 0; case 'v': printf("Version 1.0\n"); return 0; case 'o': output_file = optarg; printf("Output file: %s\n", output_file); break; case '?': fprintf(stderr, "Unknown option: -%c\n", optopt); return 1; default: fprintf(stderr, "Error\n"); return 1; } } // 处理剩余非选项参数(argv[optind] 开始) for (int i = optind; i < argc; i++) { printf("Non-option argument: %s\n", argv[i]); } return 0; } ``` --- ### **常见问题** 1. **选项参数获取** - 必须使用 `optarg` 获取参数(如 `-o file` 中 `optarg` 指向 `"file"`) 2. **错误处理** - 当 `getopt` 返回 `?` 时,检查 `optopt` 以确定非法选项 3. **非选项参数** - 解析结束后,剩余参数通过 `argv[optind]` 到 `argv[argc-1]` 访问 --- ### **扩展知识** - **`getopt_long`**:支持长选项(如 `--help`),需 `<getopt.h>`,语法更复杂 - **`argp`**:GNU 高级参数解析库,适合复杂场景 --- 通过 `getopt`,可以高效地实现符合 Unix 惯例的命令行工具。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值