我爱getopt解析 argv 参数中的选项。不幸的是,我无法使 getopt
解析位于非选项之间或位于 argv
末尾的选项。示例程序:
#include <stdio.h>
#include <unistd.h>
int o_help = 0;
int main(int argc, char *argv[]) {
int opt, i;
while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) {
case 'h':
o_help = 1;
break;
default:
return -1;
}
}
printf("o_help=%d\n", o_help);
for (i = 1; i < argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
在 macOS Mojave 上的 alpine 容器中运行该程序,我得到以下输出:
$ gcc prog.c
$ ./a.out hello -h world
o_help=0
hello -h world
$ ./a.out -h hello world
o_help=1
-h hello world
官方 getopt
手册页指出:
By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end.
由于我没有另外指定,我希望默认行为为 1. 解析 -h
选项并 2. 排列 argv
以便非选项位于末尾数组的。不幸的是,调用像 ./a.out hello -h world
这样的程序既不会解析 -h
也不会排列数组。我们将不胜感激。
最佳答案
Marco 的答案是正确的,但是如果你不使用基于 glibc 的发行版,“自己安装 glibc”确实不是一个好建议;您将自己构建一个完整的并行图书馆生态系统。对于您的问题,有几个更简单的规范解决方案。
GNU 认可的使用非标准 GNU 行为(如您想要的行为)的方法是使用 gnulib 和 autoconf,它可以根据需要自动用 GNU 版本替换 getopt。然而,这是一个重大的改变,它要求您的程序是 GPL 的。
一个更简单的解决方案是仅将 getopt_long
与长选项的简并列表一起使用,而不是 getopt
。由于 getopt_long 不是标准管理的函数,而是最初在 GNU 上定义的扩展,因此 musl 的实现可以自由地遵循排列 argv
的 GNU 行为,以允许混合选项和非选项参数,并且这样做。
关于C 的 getopt 无法解析 argv 末尾(或中间)的选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60137475/