C';s getopt无法分析argv末尾(或中间)的选项

C';s getopt无法分析argv末尾(或中间)的选项,c,glibc,getopt,unistd.h,C,Glibc,Getopt,Unistd.h,我喜欢解析argv参数中的选项。不幸的是,我无法对非选项之间或argv末尾的getopt解析选项。示例程序: #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) {

我喜欢解析
argv
参数中的选项。不幸的是,我无法对非选项之间或
argv
末尾的
getopt
解析选项。示例程序:

#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;
}
官方的
getopt
手册页说明:

默认情况下,getopt()在扫描argv时会排列argv的内容,因此最终所有非选项都位于末尾


因为我没有另外指定,所以我希望默认行为为1。解析
-h
选项和2。排列
argv
,使非选项位于数组的末尾。不幸的是,像调用
/a.out hello-h world
这样的程序既不能解析
-h
也不能排列数组。非常感谢您的帮助。

您正在查看手册页面中的
getopt()
版本。Alpine Linux不使用glibc,而是使用

查看两者之间的差异,您可以从musl libc wiki中阅读:

GNU getopt将argv置于非选项参数之前,将选项拉到前面musl和POSIX标准getopt在第一个非选项参数处停止处理选项,不进行排列

因此,这里的解决方案是:

  • 在调用
    getopt()
    之前,请使用musl,但请自己排列
    argv
  • 安装glibc或使用

  • Marco的回答是正确的,但是如果您没有使用基于glibc的发行版,“自己安装glibc”确实不是一个好建议;你将独自构建一个完整的平行图书馆生态系统。对于您的问题,有两种标准的解决方案,它们要简单得多

    GNU认可的使用非标准GNU行为(如您想要的)的方法是使用gnulib和autoconf,它可以根据需要自动用GNU版本替换getopt。然而,这是一个巨大的变化,它要求你的程序是GPL的


    一个更简单的解决方案是只使用
    getopt_long
    和一个退化的长选项列表,而不是
    getopt
    。由于
    getopt_long
    不是一个标准的受管函数,而是最初在GNU上定义的扩展,musl对它的实现可以自由地遵循GNU的行为,即排列
    argv
    ,以允许混合选项和非选项参数,并且这样做。

    无法复制(使用Ubuntu)。您是否设置了正确的环境变量?对于glibc版本的
    getopt()
    ,这将给出您看到的结果。(我假设alpine容器指的是alpine Linux虚拟机。如果它是其他东西,并且您使用的是OS X版本的
    getopt()
    ,但查看glibc文档…)实际上,alpine使用的是musl,而不是glibc。所以,是的。确定您看到的是正确的文档吗?@Shawn我正在使用docker,它在OS X上作为进程运行。我使用
    apk add libc dev
    安装了标准库,我不确定这是否是
    glibc
    实现。但您可能是对的,例如,上的OS X手册页没有提供这样的行为:“当所有选项都已处理(即,直到第一个非选项参数),getopt()返回-1如果您没有使用基于glibc的发行版,“自行安装glibc”确实不是一个好建议;你将独自构建一个完整的平行图书馆生态系统。我将发布一个更好的替代方案。@R..GitHubSTOPHELPINGICE您不打算自己构建任何东西,它已经打包并可在一秒钟内安装。OP将需要构建他们正在编写/构建的任何软件,这可能取决于库的生态系统,而不仅仅是libc。此外,Apline没有提供用于针对glibc进行编译的glibc交叉编译器,因此他们也必须进行设置。非常感谢,我从来没有检查过
    getopt_long
    的文档-这非常棒,事实上,我刚刚检查过
    musl
    实现,它还将argv置换到
    musl
    实现中。
    $ 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