【问题标题】:getopt order of argv when passing multiple arguments to one option将多个参数传递给一个选项时的 argv 的 getopt 顺序
【发布时间】:2020-08-12 19:29:22
【问题描述】:

我正在尝试将多个参数传递给一个选项。 例如,

(1)./someProgram -f opt1 opt2 opt3 -j opt -d.

(2)./someProgram -f /dir/dir/* -j opt -d.

我的 getopt_long 设置如下所示。

const char *short_opt = "hp:j:o:f:";
    struct option long_opt[] =
            {
                    {"help",      no_argument,       NULL, 'h'},
                    {"journal",   required_argument, NULL, 'j'},
                    {"partition", required_argument, NULL, 'p'},
                    {"output",    required_argument, NULL, 'o'},
                    {"file",      required_argument, NULL, 'f'},
                    {NULL, 0,                        NULL, 0}
            };

我尝试简化主要代码,以使其看起来不至于不堪重负。 我留下了与 getopt_long 变量交互的部分。

while ((arg = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
        switch (arg) {
            case -1:
            case 0:        
                break;
            ...
            case 'j':
                if (optarg) {
                    setSomeVar; //And nothing else, only set var and break.
                }
                break;
            case 'f':
                if (optarg) {
                    index = optind - 1;
                    while (index < argc) {
                        nextOpt = strdup(argv[index]);
                        index++;
                        if (nextOpt[0] != '-') {
                            callFunc(nextOpt);
                        }
                        else {
                            break;
                        }
                    }
                    optind = index - 1;
                }
                else {
                    fprintf(stderr, "...\n");
                    exit(EXIT_FAILURE);
                }
                break;
            case ':':
            case '?':
                fprintf(stderr, "...");
                return (EXIT_FAILURE);

            default:
                fprintf(stderr, "...", argv[0], arg);
                return (EXIT_FAILURE);
        };

如果我像下面这样调用我的程序,一切都会按预期进行。

第一个输入

./prog -f /dir/dir/* - (60 files) or ./prog -f file1 file2 file3
info about file1
info about file2
... and so on

如果我要在末尾添加另一个选项。

第二次输入

./prog -f file1 file2 file3 file4 -j smth
info about1 file1
action with -j smth. **End.**

我试图在开头列出所有参数,第二个输入如下:

for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
}

结果如预期(第二次输入)

-f, file1,file... -j,print

我再次将这个 for 循环包含在我的 switch 中,在 'f' 的情况下。 使用第二个输入,我看到已经有 3 个参数是 -j,而第 4 个是 j 的选项,只有在那之后才有所有其他文件。 输出就像你已经猜到了,

file1, -j, print, file2, file3,file4

我的问题是为什么会这样?或者我应该如何解决它,或者我需要看看? 我还尝试改进我的代码,查看这里回答的几个类似问题,但看起来我已经遵循了所有建议。

Parsing command line options with multiple arguments [getopt?]

C getopt multiple value

Get several values for the same option [duplicate]

通过在引号中传递所有参数的解决方案对我不起作用,因为用户可能希望重定向来自 ls 的输入,例如,或者在最后传递带有 * 的目录。

谢谢你:)

【问题讨论】:

  • 为什么不只是./someProgram -f opt1 -f opt2 -f opt3 -j opt -d
  • @KamilCuk,因为如果你调用这样的程序./p -f /dir/dir/* -j opt -d 它将不起作用。
  • 请不要破坏您自己的帖子。当您在此处发布时,即表示您授予 SO 在 CC-by SA 4.0 下分发内容的权利。任何破坏行为都将被撤销。

标签: c arguments getopt optional-arguments getopt-long


【解决方案1】:

这是关于man getopt 中的第六段(对于 Gnu 版本,您显然正在使用):

默认情况下,getopt() 会在扫描时置换 argv 的内容,以便最终所有非选项都位于末尾。还实现了另外两种模式。如果 optstring 的第一个字符是 '+' 或设置了环境变量 POSIXLY_CORRECT,则一旦遇到非选项参数,选项处理就会停止。如果 optstring 的第一个字符是 '-',则每个非选项 argv 元素都被处理为就好像它是具有字符代码 1 的选项的参数一样。(这被编写为期望选项和其他 argv 元素的程序使用以任何顺序,并且关心两者的顺序。)特殊参数“--”强制结束选项扫描,无论扫描模式如何。

我认为您可以使用任何一种非默认模式使您的代码工作,但为了可移植性,我会使用 Posix 标准模式。

(虽然我实际上鼓励您不要使用非标准实用程序参数约定。选项应该采用一个参数;如果您想要的话,在列表中重复一个选项很容易。)

【讨论】:

  • 是否可以将讨论结束并从中获得剩余选项的决定视为好的设计?或者在开始时获取所有剩余的选项,然后调用 getopt_long - 我认为这会更容易。并感谢您的帮助:)
  • @hero1n: getoptgetopt_long 是相同的,只是 getopt_long 处理长选项名称。默认情况下,它们都会置换。就个人而言,我认为您可能不需要-f 标志;只需在选项完成后保留所有参数即可。但这将取决于您的实用程序的确切性质。
  • 解决方案根本不使用标志,似乎更好。非常感谢,感谢您的帮助:)
猜你喜欢
  • 2014-11-10
  • 2019-03-04
  • 1970-01-01
  • 2023-03-25
  • 2014-04-08
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多