getopt_long为解析命令行参数函数,它是Linux C库函数。使用此函数需要包含系统头文件getopt.h。
getopt_long函数声明如下:
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
getopt_long的工作方式与getopt类似,关于getopt的介绍可以参考: https://blog.csdn.net/fengbingchun/article/details/81122843 。但是getopt_long除了接受短选项外还接受长选项,长选项以"--"开头。如果程序只接受长选项,那么optstring应指定为空字符串。如果缩写是唯一的,那么长选项名称可以缩写。长选项可以采用两种形式:--arg=param或--arg param. longopts是一个指针指向结构体option数组。
结构体option声明如下:
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
name:长选项的名字
has_arg:0,不需要参数;1,需要参数;2,参数是可选的
flag:指定如何为长选项返回结果。如果flag是null,那么getopt_long返回val(可以将val设置为等效的短选项字符),否则getopt_long返回0.
val:要返回的值。
结构体option数组的最后一个元素必须用零填充。
当一个短选项字符被识别时,getopt_long也返回选项字符。对于长选项,如果flag是NULL,则返回val,否则返回0。返回-1和错误处理方式与getopt相同。
下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
CMakeLists.txt文件内容如下:
PROJECT(samples_cplusplus)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
# 支持C++11
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2 -std=c++11")
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
FILE(GLOB samples ${PROJECT_SOURCE_DIR}/*.cpp)
FOREACH (sample ${samples})
STRING(REGEX MATCH "[^/]+$" sample_file ${sample})
STRING(REPLACE ".cpp" "" sample_basename ${sample_file})
ADD_EXECUTABLE(test_${sample_basename} ${sample})
TARGET_LINK_LIBRARIES(test_${sample_basename} pthread)
ENDFOREACH()
sample_getopt_long.cpp内容如下:
#include
#include
#include
int main(int argc, char* argv[])
{
// reference: http://man7.org/linux/man-pages/man3/getopt.3.html
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", required_argument, 0, 0},
{"append", no_argument, 0, 0},
{"delete", required_argument, 0, 0},
{"verbose", no_argument, 0, 0},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 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:
//fprintf(stdout, "option %s ", long_options[option_index].name);
//if (optarg) fprintf(stdout, "with arg %s", optarg);
//fprintf(stdout, "\n");
if (strcmp(long_options[option_index].name, "add") == 0)
fprintf(stdout, "long option \"add\" value: %s\n", optarg);
else if (strcmp(long_options[option_index].name, "append") == 0)
fprintf(stdout, "long option \"append\"\n");
else if (strcmp(long_options[option_index].name, "delete") == 0)
fprintf(stdout, "long option \"delete\" value: %s\n", optarg);
else if (strcmp(long_options[option_index].name, "create") == 0)
fprintf(stdout, "long option \"create\" value: %s\n", optarg);
else if (strcmp(long_options[option_index].name, "verbose") == 0)
fprintf(stdout, "long option \"verbose\"\n");
else if (strcmp(long_options[option_index].name, "file") == 0)
fprintf(stdout, "long option \"file\" value: %s\n", optarg);
break;
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind)
fprintf(stdout, "digits occur in two different argv elements.\n");
digit_optind = this_option_optind;
fprintf(stdout, "option %c\n", c);
break;
case 'a':
fprintf(stdout, "option a\n");
break;
case 'b':
fprintf(stdout, "option b\n");
break;
case 'c':
fprintf(stdout, "option c with value '%s'\n", optarg);
break;
case 'd':
fprintf(stdout, "option d with value '%s'\n", optarg);
break;
case '?':
break;
default:
fprintf(stdout, "?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
fprintf(stdout, "non-option argv elements: ");
while (optind < argc)
fprintf(stdout, "%s ", argv[optind++]);
fprintf(stdout, "\n");
}
exit(EXIT_SUCCESS);
}
bash.sh内容如下:
#! /bin/bash
real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"
new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make
cd -
run_getopt_long.sh内容如下:
#! /bin/bash
real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"
echo -e "\n\ntest argv1:"; ${dir_name}/build/test_sample_getopt_long
echo -e "\n\ntest argv2:"; ${dir_name}/build/test_sample_getopt_long -?
echo -e "\n\ntest argv3:"; ${dir_name}/build/test_sample_getopt_long --add xxx
echo -e "\n\ntest argv4:"; ${dir_name}/build/test_sample_getopt_long -a xx -b yy -c zz -d rr -0 ss -1 tt -2 qq
echo -e "\n\ntest argv5:"; ${dir_name}/build/test_sample_getopt_long --add Tom --append Jim --delete Rucy --verbose XXX --create new_data --file a.txt -ab -c 111 -d 222
echo -e "\n\ntest argv6:"; ${dir_name}/build/test_sample_getopt_long -xxx yyy
echo -e "\n\ntest argv7:"; ${dir_name}/build/test_sample_getopt_long -a
执行过程:首先执行build.sh,然后再执行run_getopt_long.sh即可。
GitHub: https://github.com/fengbingchun/Linux_Code_Test