我一直在研究一个模仿Shell终端的程序,遇到的实现问题比我预期的要难。基本上,我正在尝试拆分参数,就像外壳如何传递给可执行文件一样。因此,想象一下像这样的输入:

$> ./foo some arguments

人们希望传递给程序的参数是一个数组,例如(假设C / C ++):

char ** argv = {"foo", "some" "arguments"}

但是,如果参数是:

$> ./foo "My name is foo" bar

数组将是:

有人可以建议一种有效的方法来实现此目的吗,这样的界面就像:

char ** argv = {"foo", "My name is foo", "bar"}vector<string> splitArgs(string allArgs);

我当然可以,只是简单地迭代并在“读单词” /“读带引号的文本”的状态之间切换,但是我觉得那没有达到应有的效果。我也对regex的想法很感兴趣,但是我对C ++的实现方式还不太熟悉。对于这个项目,我确实也安装了boost库,如果有帮助的话。

谢谢!
RR

评论

“但是我觉得那没有达到应有的效果。”……确实,最好还是这样做并获得一个有效的外壳。无论如何-既然您已经问过-请检查stackoverflow.com/questions/541561/…以获取使用Boost令牌生成器的解决方案。

只需逐步浏览每个角色,然后看看您拥有什么。这是我在C#中做到的方式。我不确定RegEx是否会在这里为您提供所需的信息。

太好了,谢谢大家。我想这就是我想知道的。

实现它是步骤2。步骤1是对其进行定义。检查您最喜欢的shell的文档以找到可以使用的定义。注意事项:多种引号;括弧; I / O重定向;反斜杠。 (另外,您真的要从第一个标记中去除前两个字符吗?为什么?)

可能相关:stackoverflow.com/q/21959706/544721

#1 楼

我有时仍然为此使用普通的C实用程序功能。我主要在标准库非常有限的嵌入式系统上使用此代码,因此可以使用标准lib控件将大多数代码更改为更有效,但是基本技术应保持不变,标记字符串的引号部分在解析之前,只需将标记分开就可以将字符串拆分成单独的标记,最后消除各个部分中的引号。

/**
 * Split a line into separate words.
 */
static void splitLine(char *pLine, char **pArgs) {
    char *pTmp = strchr(pLine, ' ');

    if (pTmp) {
        *pTmp = 'q4312078q';
        pTmp++;
        while ((*pTmp) && (*pTmp == ' ')) {
            pTmp++;
        }
        if (*pTmp == 'q4312078q') {
            pTmp = NULL;
        }
    }
    *pArgs = pTmp;
}



/**
 * Breaks up a line into multiple arguments.
 *
 * @param io_pLine Line to be broken up.
 * @param o_pArgc Number of components found.
 * @param io_pargc Array of individual components
 */
static void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv) {
    char *pNext = io_pLine;
    size_t i;
    int j;
    int quoted = 0;
    size_t len = strlen(io_pLine);

    // Protect spaces inside quotes, but lose the quotes
    for(i = 0; i < len; i++) {
        if ((!quoted) && ('"' == io_pLine[i])) {
            quoted = 1;
            io_pLine[i] = ' ';
        } else if ((quoted) && ('"' == io_pLine[i])) {
            quoted = 0;
            io_pLine[i] = ' ';
        } else if ((quoted) && (' ' == io_pLine[i])) {
            io_pLine[i] = '';
        }
    }

    // init
    MY_memset(o_pArgv, 0x00, sizeof(char*) * C_MAXARGS);
    *o_pArgc = 1;
    o_pArgv[0] = io_pLine;

    while ((NULL != pNext) && (*o_pArgc < C_MAXARGS)) {
        splitLine(pNext, &(o_pArgv[*o_pArgc]));
        pNext = o_pArgv[*o_pArgc];

        if (NULL != o_pArgv[*o_pArgc]) {
            *o_pArgc += 1;
        }
    }

    for(j = 0; j < *o_pArgc; j++) {
        len = strlen(o_pArgv[j]);
        for(i = 0; i < len; i++) {
            if('' == o_pArgv[j][i]) {
                o_pArgv[j][i] = ' ';
            }
        }
    }
}


#2 楼

只是将整个字符串传递到外壳可能会满足您的需求:

例如:

更好的方法似乎是编写一个解析器来查找每个参数并将其传递给exec样式函数。