所以我试图设置一个能正确解析以下输入类型的函数(注意这个输入是乱七八糟的,只是为了试图说明我的例子)
"./test script";ls -a -o;mkdir "te>st";ls > somefile.txt
每个命令用';'分隔并且每个参数由空格''分隔,除非它们被包裹在“”中,在这种情况下它们应被视为字面或整体。 IE我想要的输出是
cmd:“。/ test script”
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, " ");
}
}
答案 0 :(得分:0)
当你必须处理复杂规则(带有双引号的字段),制作自己的函数或使用某个库时,避免使用strtok
,我建议你去看libcsv,一个用纯ANSI C89编写的小而简单的库。
答案 1 :(得分: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, ';');
}
}
这只会修复命令解析的前半部分。第二部分可以使用相同的例程处理,或者 - 据我所知 - 使用沼泽标准strtok
。
顺便说一句,我的例程中的static char
使不可重入 - 不使用交替字符串。 (可能你已经知道了,因为你也在自己的代码中避免使用它。)