命令行选项参数解析-getopt函数

本文详细介绍了Unix/Linux编程中的getopt、getopt_long和getopt_long_only函数,包括它们的功能、参数解释、短参数定义、optind变量、返回值等关键信息。通过实例展示了如何在实际调用中正确使用这些函数,提供了丰富的编程实践指导。

在学习Unix/Linux编程实践教程时,编写练习一些linux命令,需要对命令行参数进行解析,从而接触到getopt系列函数:

1. getopt()

2. getopt_long()

3.getopt_long_only()

总结如下:

Parse command-line options

 
NAME
getopt, getopt_long, getopt_long_only, optarg, optind, opterr, optopt - Parse command-line options
 
SYNOPSIS
#include <unistd.h>
 
int getopt(int argc, char * const argv[],
const char *optstring);
 
extern char *optarg;
extern int optind, opterr, optopt;
 
#include <getopt.h>
 
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);

1. getopt()函数

函数说明

getopt()用来分析命令行参数。参数argc和argv是由main()传递的参数个数和内容。参数optstring 则代表欲处理的选项字符串。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。

optopt:如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符, 
opterr:将全域变量opterr设为0,getopt()不打印出错信息 
optarg:选项的参数指针

短参数的定义

getopt()使用optstring所指的字串作为短参数列表,“lba:d::”这就是一个短参列表,命令行使用时应加上“-”(即“-l”), 

其中短参数在getopt定义里分为三种:

  • 不带值的参数,它的定义即是参数本身。
  • 必须带值的参数,它的定义是在参数本身后面再加一个冒号。
  • 可选值的参数,它的定义是在参数本身后面加两个冒号 。

在实际调用中,’-l -b -a ty -d’, ‘-lb -a ty -ddvalue’, ‘-lb -a ty -ddvalue’都是合法的。这里需要注意三点:

  • 不带值的参数可以连写,-l 和-b,它们可以-l -b分开写,也可以-lb或-bl连写。
  • 参数不分先后顺序
  • 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误,必选参数的值和参数之间可有空格也可没有。

optind

变量optind 是argv中要被处理的下一个元素的索引。初始值为1,最大值为optstring中定义的选项个数(有可选(::)参数的算一个;必选(:)参数选项和参数之间没空格算一个,有空格算两个)加 1 ,getopt会遍历argv,每次调用后都会让optind指向下一个option在argv中的索引,每次optind移动多少取决于optstring中的字段:

  • 遇到”x”,选项不带参数,optind += 1
  • 遇到“x:”,带参数的选项,optarg = argv[optind + 1], optind += 2
  • 遇到“x::”,可选参数,属于#1和#2之一,GNU扩展实现。 
    如果一切顺利,最后optind应该指向第一个非option参数,如果optind >= argc,说明没有已经没有参数了。如果遇到不认识的参数或丢失的参数,另外两个全局变量“opterr, optopt”就派上用场了,剩下的就看文档和源代码吧。

返回值

getopt()每次调用会逐次返回命令行传入的参数。
当没有参数的最后的一次调用时,getopt()将返回-1。
当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。
当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' 。
  
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
 
int main(int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
nsecs = 0;
tfnd = 0;
flags = 0;
while ((opt = getopt(argc, argv, "nt:")) != -1) {
switch (opt) {
case 'n':
flags = 1;
break;
case 't':
printf("-t %s\n",optarg);
tfnd = 1;
break;
default: /* '?' */
fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
printf("flags=%d; tfnd=%d, optind=%d, argc=%d\n", flags, tfnd, optind,argc);
if (optind >= argc) {
fprintf(stderr, "Expected argument after options\n");
exit(EXIT_FAILURE);
}
 
printf("argv[optind] name argument = %s\n", argv[optind]);
exit(EXIT_SUCCESS);
}
  
[ty@ty argument]$ ./a.out -tty name
-t ty
flags=0; tfnd=1, optind=2, argc=3
argv[optind] name argument = name
[ty@ty argument]$ ./a.out -t ty name
-t ty
flags=0; tfnd=1, optind=3, argc=4
argv[optind] name argument = name

2. getopt_long()函数

getopt_long支持长选项的命令行解析,函数中的参数argc和argv通常直接从main()的两个参数传递而来

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

getopt_long支持长选项的命令行解析: 
参数argc和argv通常直接从main()的两个参数传递而来。 
optstring是选项参数和getopt函数一致; 
longopts指定长选项,是个结构体指针,结构体如下:

  
struct option {
const char *name; //name表示的是长参数名
int has_arg
int *flag; //用来决定,getopt_long()的返回值到底是什么。如果flag是null,则函数会返回与该项option匹配的val值
int val; //和flag联合决定返回值
}

has_arg有3个值:

  • no_argument(或者是0),表示该参数后面不跟参数值
  • required_argument(或者是1),表示该参数后面一定要跟个参数值
  • optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值

在实际情况中,我们还希望每个长选项都对应一个短选项,此时在option结构中,只需将flag设置为NULL,并将val设置为长选项所对应的短选项字符即可。

实例如下:

  
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <getopt.h>
 
int main(int argc, char **argv)
{
int c;
int digit_optind = 0;
 
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 1, 0, 'c'},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
 
c = getopt_long(argc, argv, "abc:d:012",
long_options, &option_index);
if (c == -1)
break;
 
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
 
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;printf("option %c\n", c);
break;
case 'a':
printf("option a\n");
break;
case 'b':
printf("option b\n");
break;
case 'c':
printf("option c with value '%s'\n", optarg);
break;
case 'd':
printf("option d with value '%s'\n", optarg);
break;
case '?':
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);}
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
exit(EXIT_SUCCESS);
}

3. getopt_long_only()函数

该函数和getopt_long功能基本相同,只不过它还可以支持一个“-”的长选项(即 “-name”)


编写的一个类find命令的程序sfind,使用getopt_long_only解析参数选项

https://github.com/ty92/sfind
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值