基于GLib在C语言中实现保留引号的字符串分割
刚好我之前也遇到过类似的需求——想用GLib实现类似Python shlex.split(s, posix=False)的字符串拆分:按空格分割文本,但把引号包裹的内容当作一个整体,同时保留引号本身。确实g_strsplit完全搞不定这个,因为它只认简单的分隔符,根本不处理引号的特殊规则。
解决方案:手动实现带引号保留的拆分函数
因为GLib没有直接提供完全匹配你需求的现成函数,最稳妥的方式是自己写一个简单的字符串遍历处理函数,逻辑和shlex.split(posix=False)对齐:
#include <glib.h> #include <ctype.h> GList* split_with_quotes(const gchar* str) { GList* tokens = NULL; GString* current_token = g_string_new(""); gboolean in_quotes = FALSE; const gchar* p = str; while (*p != '\0') { if (*p == '"') { // 切换引号状态,同时把引号本身加入当前token in_quotes = !in_quotes; g_string_append_c(current_token, *p); p++; } else if (!in_quotes && g_ascii_isspace(*p)) { // 不在引号内且遇到空格,结束当前token if (current_token->len > 0) { tokens = g_list_append(tokens, g_string_free(current_token, FALSE)); current_token = g_string_new(""); } // 跳过连续的空格 while (*p != '\0' && g_ascii_isspace(*p)) { p++; } } else { // 普通字符,直接加入当前token g_string_append_c(current_token, *p); p++; } } // 处理最后一个未完成的token if (current_token->len > 0) { tokens = g_list_append(tokens, g_string_free(current_token, FALSE)); } else { g_string_free(current_token, TRUE); } return tokens; } // 使用示例 int main() { const gchar* input = "Hello World! My name is \"John Smith\""; GList* tokens = split_with_quotes(input); g_print("拆分结果:\n"); for (GList* l = tokens; l != NULL; l = l->next) { g_print("* %s\n", (gchar*)l->data); } // 记得释放内存,避免泄漏 g_list_free_full(tokens, g_free); return 0; }
函数逻辑说明
- 遍历输入字符串,维护一个
in_quotes标记,判断当前是否处于引号包裹的范围内 - 遇到引号时,切换标记状态,并将引号本身保留到当前token中
- 不在引号内时,空格作为分隔符,结束当前token并开始新的token(同时跳过连续空格)
- 所有字符(包括引号内的空格)都会被加入当前token,直到遇到分隔符或字符串结束
运行这段代码后,你会得到完全符合需求的输出:
- Hello
- World!
- My
- name
- is
- "John Smith"
内容的提问来源于stack exchange,提问作者oxibts
相关产品推荐
相关产品推荐

