Reference:
在 LInux 中,经常需要各种命令,这些函数是如何解析的呢?一种方式是使用 GNU C 提供的函数 getopt
、getopt_long
或 getopt_long_only
来解析命令行参数。
命令行参数可以分为两类,一类是短选项,一类是长选项,短选项
在参数前加一杠“-”,长选项
在参数前连续加两杠“–”,如下表所示:其中 -a,-A,-b 都表示短选项,–all,–almost-all,–author 都表示长选项,他们两者后面都可选择性添加额外参数。如:–block-size=SIZE,其中 SIZE 便是额外参数。
getopt
函数只能处理短选项,而 getopt_long
函数两者都可以,可以说 getopt_long 函数包含了 getopt 的功能。因此,这里只介绍 getopt_long 函数。而 getopt_long 与 getopt_long_only 区别很小,等介绍完 getopt_long 后再提起会更好。
#include // getopt 函数所在头文件
extern char *optarg;
extern int optind, opterr, optopt;
#include // getopt_long 函数所在头文件
int getopt(int argc, char * const argv[],const char *optstring);
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);
短选项
字符串;a:b::cd
,分别表示程序支持的命令行短选项有 -a、-b、-c、-d,冒号含义如下:长选项
结构体:struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"cfg", required_argument, 0, 'f'},
{"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 },
{nullptr, 0, nullptr, 0}
};
(1)name:表示选项的名称,如 help、cfg 等;
(2)has_arg:表示选项后面是否携带参数,该参数有三个不同值,如:
no_argument(0): 参数后面不跟参数值,如:–help;
required_argument(1): 参数输入格式为:–参数 值 or –参数=值,如:./dist_measurment_node --cfg ./cal_result;
optional_argument(2): 参数输入格式只能为:–参数=值。
(3)flag:该参数有两种,空或者非空:
如果参数为空(NULL):当选中某个长选项的时候,getopt_long 将返回 val 值,如: ./可执行程序 --help
,getopt_long 的返回值为 h。
如果参数不为空:当选中某个长选项的时候,getopt_long 将返回 0,并且将 flag 指针指向 val 值,如:./可执行程序 --http-proxy=127.0.0.1:80
,getopt_long 的返回值为 0,并且 lopt 值为 1。
(4)val:表示指定函数找到该选项时的返回值,或者当 flag 非空时指定 flag 指向的数据的值。
如果短选项找到,那么将返回短选项对应的字符。
如果长选项找到,如果flag为NULL,返回val。如果flag不为空,返回0
如果遇到一个选项没有在短字符、长字符里面,或者在长字符里面存在二义性的,返回“?”
如果解析完所有字符没有找到(一般是输入命令参数格式错误,eg: 连斜杠都没有加的选项),返回“-1”
如果选项需要参数,忘了添加参数。返回值取决于optstring,如果其第一个字符是“:”,则返回“:”,否则返回“?”。
注意:
longopts的最后一个元素必须是全0填充,否则会报段错误
短选项中每个选项都是唯一的。而长选项如果简写,也需要保持唯一性。
#include
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"cfg", required_argument, 0, 'f'},
{nullptr, 0, nullptr, 0}
};
static void HelpInfo(char *argv[]) {
printf("Usage: %s --cfg or -f \n" , argv[0]);
}
int main(int argc, char *argv[])
{
int status = 0;
int arg, index;
std::string cfg_file;
arg = getopt_long(argc, argv, "hf:", long_options, &index);
if (arg == -1) { //见上文2.3.4:如果解析完所有字符没有找到,返回“-1”
HelpInfo(argv); //传递入可执行文件名
return -1;
} else {
switch (arg) {
case 'h':
HelpInfo(argv);
return 0;
case 'f':
if (optarg) {
cfg_file = optarg; //见上文2.2.1:会被系统自动赋为当前选项的参数,如:./可执行程序 -f Shuaiji,下面一句会打印:Use cfg: Shuaiji
printf("Use cfg: %s\n", cfg_file.c_str());
} else {
HelpInfo(argv);
return -1;
}
}
}
return status;
}