【问题标题】:Argument-parsing helpers for C/UnixC/Unix 的参数解析助手
【发布时间】:2010-09-16 10:34:25
【问题描述】:

我知道以下几点:

  • 可敬的getopt(3)
  • 扩展getopt_long
  • glibc 的 argp Unix 风格参数向量解析器
  • popt 来自 GNOME 项目(或其精神继承者 Glib

我确信还有更多我没有使用过甚至没有听说过的东西;快速的 Google 搜索显示 GoptargtableOptlist

就我个人而言,我最喜欢argp,而且我使用getopt/getopt_long 编写的每个程序(超出一定的复杂性基线)都已转换为使用argp。它比popt 更广泛可用,比getopt_long 更强大,有据可查,符合所有GNU 风格的约定,而且非常灵活。不利的一面是,它远非最容易使用(由于非常灵活),并且支持它的代码非常冗长(就像 C 中的许多东西一样)。

你用什么,为什么?

是的,我指的是 C 而不是 C++。有很多 C++ 解析器,但我不使用 C++。

John Millikin 指出 popt 不再维护。我之所以列出它,是因为许多程序仍在使用它——包括 AbiWord、rpm、rsync 和 samba——尽管 Gnome 努力使用migrate away。但我现在也添加了指向 Glib 参数解析器的链接。


对于 C++ 参数解析,请参阅问题What parameter parser libraries are there for C++?

【问题讨论】:

    标签: c command-line parsing


    【解决方案1】:

    我一直在开发和使用libparamset,这是一个用纯C语言编写的命令行参数解析库。它提供:

    • 跨平台功能(Linux、OS X、Windows)。
    • 可配置的解析器,其中每个参数的作用不同(强大而灵活的功能)。
    • 自动生成的拼写错误、未知参数或无效参数的消息。
    • 设计命令行用户界面的额外功能。
    • 良好的文档。

    【讨论】:

      【解决方案2】:

      因为我在寻找同样的东西,所以我阅读了这个老话题的答案。最后我选择了What parameter parser libraries are there for C++?中提到的dropt。实际上它是用 C 实现的,所以我认为这里也值得一提。我没有使用 C++ 助手,它包装了 C 实现。

      关于 dropt 的有趣事实:

      • 轻量级
      • 仅取决于标准库
      • 没有陡峭的学习曲线
      • 足以进行基本的 arg 解析,还有一些强大的功能
      • 易于扩展
      • 非限制性许可 (zlib-ish)

      有限的。例如,我必须稍微调整一下我的参数语法规范;在这种情况下这是可以接受的,但当然有时规格是一成不变的。

      作为结论,我建议至少在快速原型设计、工具开发和内部项目中使用 dropt。

      【讨论】:

      • 绝对完美。非常感谢!
      • 哇,居然有人在使用我的图书馆! =D
      【解决方案3】:

      俗话说,“标准胜于好”。所以我总是使用 getopt_long() 和任何非 GNOME/glibby 的东西,以及 glib 的任何东西。

      出于同样的原因,我总是在 Python 应用程序中使用 optparse,尽管它相对于 getopt_long() 缺少很多功能......但这是 Python 标准。

      【讨论】:

      • 我从来没有使用过没有 glibc 的系统,但您确实有一个很好的观点,即 getopt_long 更为普遍。现在我很好奇为什么你和约翰都提到了 Python? :)
      • 我不能代表他们说话,但一般来说,我认为直接 C 程序的时间很短。我用 python 编写程序,必要时用 C 编写库。
      • 在 Python 3.x 中,该标准已重命名为 argparse。
      【解决方案4】:

      我真的很喜欢TCLAP 库,因为它非常灵活且易于使用。它也是完全基于模板的,所以它是一个只有头文件的库。

      我的错误:你说 C 而我发布了一个 C++ 库...

      【讨论】:

        【解决方案5】:

        我也不太喜欢 getopt(虽然它很标准)。我提出的一种解决方案是函数 argopt()。它与 C 兼容,可用于测试是否设置了标志以及读取带有值的选项。它只支持短选项(例如 -h),尽管为长选项(例如 --help)编写类似的函数应该不会太难。见例子:

        int main(int argc, char **argv){
        
            if(argopt(argc, argv, 'p')) printf("-p is set\n");
            if(argopt(argc, argv, 'q')) printf("-q is set\n");
        
            const char *f = argopt(argc, argv, 'f');
            if(f) printf("-f is %s\n",f);
        
            return 0;
        }
        

        命令行示例:

        $./main -f input.txt -rq
        -q is set
        -f is input.txt
        

        免责声明:我制作这个函数是为了好玩,目的是让它简短、C 兼容、易于使用并且没有依赖关系。这里是:

        const char* argopt(int argc, const char *const *argv, char key){
        
            for(int i=1; i<argc; i++){
                const char *c = argv[i];
                if(*c!='-') continue;
                while(*++c) if(*c==key) return argv[(i+1)%argc];
            }
        
            return 0;
        }
        

        【讨论】:

        • 这个方案的一个缺点是,如果用户输入./main -t -V,你永远不会报告无效的选项——你只是忽略它们(例如-r)。另一个是该函数不会将-- 处理为“选项参数的结尾”。如果有人写-finput output,你的代码报告文件名是output,而不是input。这些问题足以阻止我使用您的解决方案。碰巧的是,由于 argv[argc] 被定义为 NULL,因此您不需要模数运算。这是一个有趣的想法。
        • 是的,这就是我添加免责声明的原因。它被制作成最小的,而不是故障安全和灵活的。该示例有意使用-r 来表示这一点。 -finput 是否应该是有效输入取决于您使用的约定。我使用了应该允许标志分组的约定,例如-rq。那么-finput 将是一组标志fi 等等。当然,您可以将foption 与q 区别对待,但它不会是最小的。模数是必要的,否则搜索q 将评估为假。不过,我感谢您的反馈。
        【解决方案6】:

        GNU 有 gengetopt 生成选项数据结构的代码和 getopt_long 代码来解析命令行并填充结构。它相当容易学习并且运行良好。

        作为奖励,您可以在代码周围传递选项结构,并在需要时避免全局存储。

        它提供了 GNU 风格的语义(显然),并且如果您不确定您的受众的构建环境,它足够小,可以简单地包含在项目中以进行分发。

        【讨论】:

          【解决方案7】:

          popt 已被废弃 很长时间 -- 自三年前的 2.6 版以来,参数解析已合并到 glib

          我使用glib 的解析器,或者Python 的getopt 端口。

          【讨论】:

          • 我想知道您为什么使用 glib 的参数解析器 - 是什么让它比替代品更适合您的使用?
          • 因为与 glib 捆绑在一起。我可以学习如何使用另一个解析器,或者只使用其他人都会使用的解析器。
          • 只是评论这个问题确实问“你用什么,为什么?”......不过,Glib 的解析器看起来确实不错,所以谢谢你的回答。
          • 2009 年 4 月发布了 popt 的 1.15 版和 2010 年 5 月发布的 1.16 版。但是,如果可以相信 rpm5.org/files/popt 网站,那么从那时起就没有发布过 - 现在(2018 年 3 月)符合“未维护”的条件,即使在 2010 年年中并非严格如此。
          猜你喜欢
          • 2013-08-03
          • 2016-02-07
          • 1970-01-01
          • 2018-09-10
          • 1970-01-01
          • 1970-01-01
          • 2011-12-11
          • 2015-05-08
          • 1970-01-01
          相关资源
          最近更新 更多