【发布时间】:2010-08-16 03:31:52
【问题描述】:
如何从命令行参数“tail -10”中获取选项-10。 getopt 函数找到 '1' 字符。但是如何访问字符串 "10"?
如果这可以通过 getopt_long 完成,一个示例会有所帮助。谢谢。
【问题讨论】:
-
我怀疑 getopt 不支持单破折号多字符选项,但我不确定
如何从命令行参数“tail -10”中获取选项-10。 getopt 函数找到 '1' 字符。但是如何访问字符串 "10"?
如果这可以通过 getopt_long 完成,一个示例会有所帮助。谢谢。
【问题讨论】:
除非您打算将-1 用作以0 作为其参数的选项,否则答案是您不打算这样做。 getopt 仅用于处理符合标准 POSIX 实用程序选项语法的选项。可以使用 GNU getopt_long 来实现此目的,或者您可以编写自己的 argv 解析器(很简单)。
编辑:实际上我认为我误读了您想要的内容。如果您希望 - 后跟任何数字被解释为具有该数值的选项,我认为没有任何版本的 getopt 可以工作。您无法将每个数字作为选项进行特殊处理,如果您只是告诉 getopt 所有数字都是带参数的选项字符,-123 将被解释为带有参数的 -1 选项的23(这很好,你可以从那里解释它),但是一个单独的-1 将导致下一个argv 元素将eaten 作为-1 的参数,这很难或不可能恢复。
【讨论】:
--
getopt_long 包含一个“long-only”选项(或者可能是一个单独的函数 getopt_longonly?),它接受单个 - 或双 --。
这里发生的情况是 c 语言附带绝对没有关于处理命令行选项的正确方法的标准。
此外,unix 世界已经有很长一段时间没有这样的标准了(相信在Unix Haters Handbook (PDF link) 中有一个完整的部分)。
因此,人们编写了 ad hoc 处理机制。这些最终演变为一个通用(ish)标准,getopt 诞生了(在贝尔实验室)。后来我们得到了 GNU getopt 和 getopt_long。然而,这些不是必需的,一些程序仍然以自己的方式管理事情。
但在事情安定下来之前(有时是之后),人们在“通常”的处理选项的方式中添加了新功能只要他们看起来是个好主意。现在,tail 会比任何其他功能更频繁地调整 number 行,这是一个不错的选择,因此使其简单和很少调整击键在当时一定是个好主意...
【讨论】:
我从来没有那么喜欢 getopt,所以我照常做,重新发明了轮子。我称我的解决方案为 argopt。您可以在https://github.com/colding/argopt 获取源代码和手册页。我认为它比 getopt 更易于使用。
【讨论】:
如果可能,我建议更改命令参数语法以避免使用数字参数,方法是将数字作为选项参数传递(例如 -n -5)或仅在 -- 选项分隔符之后允许它。
对于无法更改参数语法的情况,BUGS section of the BSD getopt(3) man page 记录了一种执行此操作的方法。我已经调整了他们的解决方案以避免optreset,即not specified by POSIX和not supported by glibc:
int ch;
long num;
char *numarg;
while ((ch = getopt(argc, argv, "0123456789")) != -1) {
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
numarg = argv[optind - 1];
if (numarg[0] == '-' && numarg[1] == ch && numarg[2] == '\0') {
num = '0' - ch;
} else if ((numarg = argv[optind]) != NULL && numarg[1] == ch) {
char *ep;
int numoptind = optind;
num = strtol(numarg, &ep, 10);
if (*ep != '\0') {
fprintf(stderr, "illegal number -- %s\n", numarg);
return EXIT_FAILURE;
}
/* Advance getopt internal state to next argument. */
while (optind == numoptind) {
ch = getopt(argc, argv, "0123456789");
assert(ch >= '0' && ch <= '9');
}
} else {
fprintf(stderr, "number after other options -- %s\n", numarg);
return EXIT_FAILURE;
}
break;
default:
/* Unrecognized option character. Error printed by getopt. */
return EXIT_FAILURE;
}
}
您可以将getopt 替换为getopt_long,并根据需要添加额外的短选项或长选项。
【讨论】: