使用C中的argp解析单个选项的多个值

时间:2015-09-29 01:21:34

标签: c command-line-arguments command-line-parsing

我正在寻找一种使用argp为单个选项传递多个参数的方法。 我想以这种方式调用我的命令行工具:

./foo -l user1 user2 user3 -name bar

在这里,我希望将user1,user2和user3作为参数传递给-l选项。由于argp每个选项只接受1个参数,我该如何实现呢?

目前,我有以下结构:

struct arguments arguments;
arguments.lists = "";
arguments.name = "";
argparse (&argp, argc, argv, 0, 0, &arguments);

因此,在正确解析选项-l之后,argument.lists应该是“user1 user2 user3”而不是“user1”。 感谢

3 个答案:

答案 0 :(得分:2)

命令行上的标准语法是:

./foo -l user1 -l user2 -l user3 -name bar

大多数命令行解析库都会理解这一点。

答案 1 :(得分:0)

如何在argv[]数组中显示参数将取决于所使用的命令shell。大多数命令shell遵循普遍接受的标准,命令行参数由空格分隔,如果要指定带空格的参数,则必须引用它。

所以./foo -l user1 user2 user3 -name foo是一个命令行,它将作为七个参数提供给C运行时,第一个是程序的名称,其余六个参数为-l,{{1} },user1user2user3-name

如果在命令行中输入了foo,其中用户列表(user1,user2和user3)位于带引号的字符串中,则命令行将作为五个参数提供给C运行时, first是程序的名称,其余四个参数为./foo -l "user1 user2 user3" -name foo-l(引号通常由命令shell删除,所有引号都在同一个参数中),user1 user2 user3-name

回到UNIX C命令行实用程序的旧时代,我们将执行类似以下操作的简单命令行解析。以下源代码执行命令行类可能执行的工作。这是用C ++完成的,但是采用C风格。

当然,因为它被抛在一起,所以它不是很健壮,例如,特定命令行选项的超过30个参数会导致问题。

foo

// arglist.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> /* * argument options accepted are as follows: * -l -> indicates a user list of one or more user names follows * -name -> indicates a name for the list follows * * arguments without a leading dash are considered to be option changes * and arguments without a leading dash are considered to be arguments * for the last option. **/ typedef struct { int index; int argListIndex[30]; } argList; const int indexOptionUnknown = 0; const int indexOptionL = 1; const int indexOptionName = 2; int main(int argc, char * argv[]) { // the index into the argv[] array. zeroth element of argve[] is ignored. argList myList[3] = {0}; int iMyList = 0; // we skip the first argument which is the name of our program // we then process the remaining command line arguments which the C runtime // has provided as a series of char strings. for (int i = 1; i < argc; i++) { if (*argv[i] == '-') { // this is an argument option. figure out which one. if (strcmp (argv[i], "-l") == 0) { iMyList = indexOptionL; } else if (strcmp (argv[i], "-name") == 0) { iMyList = indexOptionName; } else { // unknown option so we will ignore it. iMyList = indexOptionUnknown; } } else { // this is an argument for the last option found if (iMyList > indexOptionUnknown) { myList[iMyList].argListIndex[ myList[iMyList].index ] = i; myList[iMyList].index++; } } } std::cout << "option -l, count of arguments " << myList[indexOptionL].index << std::endl; for (int i = 0; i < myList[indexOptionL].index; i++) { std::cout << " " << i << " is " << argv[myList[indexOptionL].argListIndex[i]] << std::endl; } std::cout << "option -name, count of arguments " << myList[indexOptionName].index << std::endl; for (int i = 0; i < myList[indexOptionName].index; i++) { std::cout << " " << i << " is " << argv[myList[indexOptionName].argListIndex[i]] << std::endl; } return 0; } 等参数行的输出为:

pgm -l user1 user2 user3 -name foo

option -l, count of arguments 3 0 is user1 1 is user2 2 is user3 option -name, count of arguments 1 0 is foo 之类的命令行将是相同的输出。该解析器的作用是在命令行上为特定选项构建参数列表。

如果提供了诸如pgm -l user1 -l user2 -l user3 -name foo之类的命令行,则输出会因引用的参数而更改,结果为:

pgm -l "user1 user2 user3" -name foo

答案 2 :(得分:-1)

不确定这是否正确,但我能够按照以下方式执行此操作:

if (strlen(arguments->lists) != 0) {
    char *temp;
    sprintf(temp, " %s", arg);
    strcat(arguments->lists, temp);
}
else {
    arguments->lists = arg;
}

这样,如果为选项-l--lists传递了额外的arg,则会根据需要附加它。