如何用正则表达式实现C程序分词时忽略引号内的空格分割?
当然可以搞定!这种场景下正则表达式正好能帮你精准控制分词的时机——只在引号外的合法位置分割,把引号内的字符串完整保留成一个分词单元,完美解决你的问题。
核心思路:跟踪引号状态
你提到的“仅当自上次分割以来遇到的引号数量为偶数时才分割”,本质就是要判断当前位置是否处于引号外(包括初始的0引号状态)。正则里可以用零宽断言来实现这个状态判断,同时还要注意处理转义引号(比如\")的情况,避免把转义的引号当成真正的引号边界。
更可靠的方案:直接匹配合法Token
其实分词的本质是识别代码里的合法单元(字符串、关键字、变量名、符号),比起“先加空格再分割”,直接用正则匹配所有合法Token的方式更稳定,也能避免很多边缘问题。针对你的C代码场景,这个正则就够用:
"([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\w+|[^\w\s]
逐个解释下每个部分:
"([^"\\]|\\.)*":匹配双引号包裹的字符串,包括带转义引号的情况(比如"He said \"Hello\""会被完整匹配)'([^'\\]|\\.)*':匹配单引号包裹的字符(比如'a'、'\n')\w+:匹配标识符和关键字(比如char、a)[^\w\s]:匹配单个语法符号(比如[、]、=、;)
用这个正则去匹配你的示例代码char a[] = "Hello World";,得到的结果就是:char、a、[、]、=、"Hello World"、;,完全符合预期。
适配你原有流程的方案:仅在引号外加空格
如果你想保留“先加空格再分割”的原有流程,也可以用正则只在引号外的符号前后添加空格,引号内的内容完全不动。比如用这个正则匹配引号外的符号:
(?=(?:[^"]*"[^"]*")*[^"]*$)([^\w\s])
把匹配到的内容替换成$1(前后加空格),处理你的示例代码后会变成char a [ ] = "Hello World" ;,再按空格分割就能得到正确结果。
C语言代码示例
如果你用C语言的POSIX正则库实现,这里有个简单的示例:
#include <stdio.h> #include <regex.h> int main() { const char *code = "char a[] = \"Hello World\";"; regex_t regex; regmatch_t matches[1]; int reti; // 编译正则表达式 reti = regcomp(®ex, "\"([^\"\\\\]|\\\\.)*\"|'([^'\\\\]|\\\\.)*'|\\w+|[^\\w\\s]", REG_EXTENDED); if (reti) { fprintf(stderr, "正则编译失败\n"); return 1; } const char *current = code; // 循环匹配所有Token while (regexec(®ex, current, 1, matches, 0) == 0) { printf("%.*s\n", matches[0].rm_eo - matches[0].rm_so, current + matches[0].rm_so); current += matches[0].rm_eo; } regfree(®ex); return 0; }
运行这段代码,就能输出你想要的分词结果,还能自动处理转义引号的场景。
内容的提问来源于stack exchange,提问作者Ohunter
相关产品推荐
相关产品推荐

