0

所以我试图设置一个函数来正确解析以下类型的输入(请注意,这个输入是胡言乱语,只是为了说明我的例子)

"./test script";ls -a -o;mkdir "te>st";ls > somefile.txt

其中每个命令由“;”分隔 并且每个参数都由空格 ' ' 分隔,除非它们被包裹在 "" 中,在这种情况下,它们应该被视为文字或整体。IE 我想要的输出是

cmd : "./test 脚本"

cmd : ls args[2] {-a, -o}

cmd:mkdir args[1] {“测试>st”}

cmd : ls args[2] {>, somefile.txt}

我试过通过 ; 拆分它 首先,然后通过''但第一个示例失败(包裹在“”中,所以应该被认为是完整的),我在使用 c 时遇到了一些问题,因为我不太熟悉该语言,有人可以帮忙吗?这就是我到目前为止所拥有的

    // Commands split with ; 
    char *cmdSplitToken = strtok(srcPointer, ";");

    // Store commands seperately so we can deal with them one by one
    while(cmdSplitToken != NULL) {      
        cmds[cmdCount++] = cmdSplitToken;
        cmdSplitToken = strtok(NULL, ";");
    }

    // Loop over commands and gather arguments
    for(int i = 0; i < cmdCount; i++) {     
        // args split with ' '
        char *argSplitToken = strtok(cmds[i], " "); 
        int argCount = 0;
        while(argSplitToken != NULL) {      
            printf("arg %s\n", argSplitToken);
            argCount++;
            argSplitToken = strtok(NULL, " ");
        }
    }
4

2 回答 2

0

strtok当您必须处理复杂的规则(带有嵌入双引号的字段),制作自己的函数或使用一些库时,避免使用,我建议看一下libcs ​​v,一个用纯 ANSI C89 编写的小而简单的库。

于 2013-07-31T05:32:19.247 回答
0

滚动你自己的strtok并检查那里的报价。(您的示例字符串不包含任何 ';' 引号内,所以也许我误解了整个问题:)

无论如何,这是我对strtok类似的粗略版本的看法,除了它只接受一个标记字符而不是字符串(但如果有必要,很容易添加)并且它对以下内容进行元解析:

  • 以开头的字符串"匹配到结尾"
  • 以开头的字符串'匹配到结尾'
  • 任何单个字符都可以通过在前面加上\

一个不匹配的"并且'只会匹配到字符串末尾的所有内容。

#include <stdio.h>

char *get_token (char *input_str, char separator)
{
    static char *last_pos;

    if (input_str)
        last_pos = input_str;
    else
        input_str = last_pos;

    if (last_pos && *last_pos)
    {
        while (*last_pos)
        {
            if (*last_pos == separator)
            {
                *last_pos = 0;
                last_pos++;
                return input_str;
            }
            if (*last_pos == '\"')
            {
                last_pos++;
                while (*last_pos && *last_pos != '\"')
                    last_pos++;
            } else
            if (*last_pos == '\'')
            {
                last_pos++;
                while (*last_pos && *last_pos != '\'')
                    last_pos++;
            } else
            if (*last_pos == '\\' && last_pos[1])
            {
                last_pos++;
            }
            last_pos++;
        }
        return input_str;
    }
    return NULL;
}

void main (void)
{
    char str[] = "\"./test; script\";ls -a\\;b -o;mkdir \"te>st\";ls > 'some;file.txt'";
    char *cmdSplitToken = get_token (str, ';');

    while (cmdSplitToken != NULL)
    {
        printf("arg %s\n", cmdSplitToken);
        cmdSplitToken = get_token (NULL, ';');
    }
}

这仅修复了命令解析的前半部分。第二部分可以使用相同的例程处理,或者 - 据我了解 - 使用 bog standard strtok

顺便说一句,static char我的例程内部使它不能重入- 不要它与交替字符串一起使用。(可能您已经知道这一点,因为您也在自己的代码中避免了它。)

于 2013-07-31T09:42:20.453 回答