C 将字符串拆分为标记,忽略用“"&引用;
我正在创建自己的命令行解析器,并使用C 将字符串拆分为标记,忽略用“"&引用;,c,string,substring,strtok,C,String,Substring,Strtok,我正在创建自己的命令行解析器,并使用strok()和\t的分隔符(空格)拆分子字符串 但是,如果子字符串包装在\“中,则不应拆分其内容是有意义的,因为子字符串需要自由包含空格字符 有什么已知的函数或简单的方法可以做到这一点吗?我非常懒得用优雅的方式来做,所以我只是用懒散的方式来做。 下面是最丑陋的功能: char* foo (char* str) { static char* p; int subcontainer = 0; int escBackslash = 0;
strok()
和\t
的分隔符(空格)拆分子字符串
但是,如果子字符串包装在\“
中,则不应拆分其内容是有意义的,因为子字符串需要自由包含空格字符
有什么已知的函数或简单的方法可以做到这一点吗?我非常懒得用优雅的方式来做,所以我只是用懒散的方式来做。 下面是最丑陋的功能:
char* foo (char* str)
{
static char* p;
int subcontainer = 0;
int escBackslash = 0;
int i = 0;
if(p == NULL)
{
p = str;
if(*p == '\\')
escBackslash = 1;
}
char* offset = NULL;
for(offset = p; *p != '\0'; p++)
{
if(*p == '\\')
{
escBackslash = 1;
i = 1;
continue;
}
if(*p == '"' && escBackslash == 0)
{
if(subcontainer < 1)
{
subcontainer = 1;
offset++;
} else subcontainer = -1;
}
if(isspace(*p) && subcontainer < 1)
{
if(i) *(p - 3) = '"';
if(i) *(p - 2) = '\0';
*(p-(-subcontainer)) = '\0';
p++;
return offset + i;
}
if(*(p+1) == '\0')
{
if(i) *(p - 2) = '"';
if(i) *(p - 1) = '\0';
if(subcontainer == -1) *p = '\0';
p++;
return offset + i;
}
escBackslash = 0;
}
return NULL;
}
没有标准的库函数来实现这一点。您可以查看Posix
wordexp
函数(如果平台上有),但在使用它时要非常小心,因为它可以执行任意shell命令(使用WRDE_NOCMD
标志帮助),并且没有定义(可能不安全)如果像这样的特殊字符,我已经在命令行解析器(实际上更像是我程序的实时解释器脚本工具)上取得了进展,我很累,我宁愿不使用这个函数,因为它可能存在于我的平台上(Windows但cygwin),这是一个非常慢的函数,可能根本没有优化,我有点懒得尝试学习如何使用这个函数,因为它看起来相当复杂。我并不是真的推荐使用它,tbh,这就是为什么我没有给出答案。如果我要回答,我会坚持“没有有用的标准函数,但这对于学习flex来说是一个不错的入门练习。”:-)不过,了解它可能会很有用。(在Windows上,实际上有一个更有用的函数。Windows shell不使用word拆分命令行,因此需要使用库函数来完成。编辑:命令行到argvw
)@rici刚刚看到了这个功能,很好的捕获。实际上可能特别适用于打算在Windows下运行的应用程序。因为我使用cygwin,而不是MSV,所以我的目标是不要将我的应用程序窗口化太多,以便于移植。也就是说,也许我可以得到strtok
实现并修改它它的行为,也许这接近于一个简单的解决方案它很容易解析引号。问题是反斜杠的正确处理,特别是在人们经常使用反斜杠作为目录分隔符的windows上。但它并不太复杂。我会使用状态机而不是strok,因为strok实际上不是很快也不是很灵活祝你好运。
int main()
{
char* str = strdup("\"\\\"test\\\"\" + \"Command 2\" \"Command2\" function \"\\\"nice\\\"\"");
printf("[%s]\n", str);
char* str1 = foo(str);
while(str1 != NULL)
{
printf("str[%s]\n", str1);
str1 = foo(NULL);
}
free(str);
return 0;
}