【发布时间】:2020-12-14 15:09:53
【问题描述】:
我正在编写一个从文本文件中解析多个命令的代码,我发现我认为这是 getopt 中的一个错误。只是想知道是否有人以前看过这个?
基本上我有一个循环,在每次迭代中我读取一个字符串,我用'strtok'将它转换为可以馈送到getopt并检查提供的选项的东西。它在某些情况下有效:
$ ./test_short
cmd -ia
-- option i
-- option a
cmd -a
-- option a
cmd -i
-- option i
但它会失败,例如:
$ ./test_short
cmd -ia
-- option i
-- option a
cmd -i -a
cmd: invalid option -- '-'
-- option unknown
-- option a
-- option a
代码可以从https://github.com/angel-devicente/test-getopt 克隆,但为了完整起见,我也在下面放置了简短选项。
知道这是一个真正的错误还是我忘记重置的其他全局变量?
谢谢,
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <string.h>
#include <unistd.h>
#define MAX_ARGS 10
#define MAX_C 100
int main(int argc, char **argv) {
int c;
char cmd[MAX_C+1];
int argc_i;
char *argv_i[MAX_ARGS];
while (1) {
// Read string, for example: cmd -i -a
fgets(cmd,MAX_C,stdin);
cmd[strlen(cmd) - 1] = 0;
if (strlen(cmd) <= 1) break;
// Transform into argc_i, argv_i, to feed to getopt
argc_i = 0;
char *p2 = strtok(cmd, " ");
while (p2 && argc_i < MAX_ARGS)
{
argv_i[(argc_i)++] = p2;
p2 = strtok(NULL, " ");
}
argv_i[argc_i] = 0;
// Reset getopt
optind = 1;
int option_index = 0;
while (1) {
c = getopt(argc_i, argv_i, "ia");
if (c == -1)
break;
switch (c) {
case 'a':
printf(" -- option a\n");
break;
case 'i':
printf(" -- option i\n");
break;
case '?':
printf(" -- option unknown\n");
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
printf("\n\n");
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
}
exit(EXIT_SUCCESS);
}
【问题讨论】:
-
不清楚您是否将
getopt()重置为迭代之间的起始状态(新的模拟命令行参数集)。确实,没有清楚地记录您是如何做到这一点的;不同的实现可能有不同的规则集。 -
他做到了:
optind = 1;。顺便说一句,optind = 0;工作正常。 This condition in glibc getopt.c is strange -
@KamilCuk — 呃;在参加电话会议时很难阅读代码。使用
optind = 0;是更有可能的方法之一。也就是说,在 Mac 上,当程序启动时,optind == 1。但是,在 Mac 上,问题不会重现。 -
我认为这是 getopt 的 glibc 实现中的一个错误,因为代码没有使用 GNU 扩展或更改
POSIXLY_CORRECT环境变量,设置optind = 1;(而不是 GNU-扫描之间的特定optind = 0;) 应该足够了。 -
检查 RHEL 7.4,问题确实重现了 — 正如我所指出的,
getopt()的不同实现有不同的重置方式,并且并不总是记录你是如何做到的。