C 字符拆分与解析

C 字符拆分与解析,c,parsing,strtok,split,C,Parsing,Strtok,Split,因此,我试图设置一个函数,该函数将正确解析以下类型的输入(请注意,此输入是jibberish,只是为了尝试并演示我的示例) 其中每个命令由“;”分隔每个参数都由空格“”分隔,除非它们被包装在“”中,在这种情况下,它们应被视为文字或整体。我想从中得到的结果是 cmd:“/测试脚本” cmd:ls args[2]{-a,-o} cmd:mkdir args[1]{“te>st”} cmd:ls args[2]{>,somefile.txt} 我已经尝试过通过;首先,然后通过“”,但是第一个示例失败了

因此,我试图设置一个函数,该函数将正确解析以下类型的输入(请注意,此输入是jibberish,只是为了尝试并演示我的示例)

其中每个命令由“;”分隔每个参数都由空格“”分隔,除非它们被包装在“”中,在这种情况下,它们应被视为文字或整体。我想从中得到的结果是

cmd:“/测试脚本”

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

cmd:mkdir args[1]{“te>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, " ");
        }
    }
//使用拆分的命令;
char*cmdSplitToken=strtok(srcPointer,“;”);
//将命令单独存储,以便我们可以逐个处理它们
while(cmdSplitToken!=NULL){
cmds[cmdCount++]=cmdSplitToken;
cmdSplitToken=strtok(NULL,“;”);
}
//循环命令并收集参数
对于(int i=0;i
当您必须处理复杂的规则(包含双引号的字段)、创建自己的函数或使用一些库时,请避免使用
strtok
,我建议您查看一个纯ANSI C89编写的小型简单库。

滚动您自己的
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, ';');
    }
}
#包括
char*get\u标记(char*input\u str,char分隔符)
{
静态字符*最后位置;
如果(输入_str)
最后一个位置=输入位置;
其他的
输入\u str=最后一个位置;
如果(最后位置和最后位置)
{
while(*最后位置)
{
if(*最后一个位置==分隔符)
{
*最后的位置=0;
last_pos++;
返回输入_str;
}
如果(*最后一个位置=“\”)
{
last_pos++;
而(*last_pos&&*last_pos!='\')
last_pos++;
}否则
如果(*最后位置='\'')
{
last_pos++;
while(*last_pos&&*last_pos!='\'')
last_pos++;
}否则
如果(*last\u pos=='\\'&&last\u pos[1])
{
last_pos++;
}
last_pos++;
}
返回输入_str;
}
返回NULL;
}
真空总管(真空)
{
字符str[]=“\”/test;脚本\“ls-a\\;b-o;mkdir \“te>st \”ls>“some;file.txt”;
char*cmdSplitToken=get_标记(str,;);
while(cmdSplitToken!=NULL)
{
printf(“arg%s\n”,cmdSplitToken);
cmdSplitToken=get_标记(NULL,;);
}
}
这只修复了命令解析的前半部分。第二部分可以使用相同的例程处理,或者——据我所知——使用bog standard
strtok


顺便说一下,我的例程中的
静态字符
使其不可重入——不要将其与交替字符串一起使用。(可能您已经知道,因为您在自己的代码中也避免了它。)

只要想到这一点:“任何单个字符都可以通过在\'前面加上前缀进行转义,只在“.”之外有效。。“和带引号的字符串。为了使它也在字符串中转义,它需要更多的代码。就我个人而言,我也倾向于另一种方法。“…”——加倍获得一个。这几乎完美地满足了我的需要,非常感谢您的帮助!谢谢你的建议:D
#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, ';');
    }
}