C 字符拆分与解析
因此,我试图设置一个函数,该函数将正确解析以下类型的输入(请注意,此输入是jibberish,只是为了尝试并演示我的示例) 其中每个命令由“;”分隔每个参数都由空格“”分隔,除非它们被包装在“”中,在这种情况下,它们应被视为文字或整体。我想从中得到的结果是 cmd:“/测试脚本” cmd:ls args[2]{-a,-o} cmd:mkdir args[1]{“te>st”} cmd:ls args[2]{>,somefile.txt} 我已经尝试过通过;首先,然后通过“”,但是第一个示例失败了(用“”包装,所以应该被认为是完整的),我在使用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} 我已经尝试过通过;首先,然后通过“”,但是第一个示例失败了
// 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 standardstrtok
顺便说一下,我的例程中的
静态字符
使其不可重入——不要将其与交替字符串一起使用。(可能您已经知道,因为您在自己的代码中也避免了它。)只要想到这一点:“任何单个字符都可以通过在\'前面加上前缀进行转义,只在“.”之外有效。。“和带引号的字符串。为了使它也在字符串中转义,它需要更多的代码。就我个人而言,我也倾向于另一种方法。“…”——加倍获得一个。这几乎完美地满足了我的需要,非常感谢您的帮助!谢谢你的建议: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, ';');
}
}