如何使用正则表达式解析类Python的三引号字符串?
嘿,这个场景我太熟悉了——之前给一个自定义脚本语言写逐行解析器时,刚好遇到过几乎一模一样的需求!其实核心逻辑真的没那么复杂,就是靠有限状态机的两个核心状态来回切换,再配合逐行扫描处理就行。我给你拆解一下具体实现思路:
核心状态定义
首先我们只需要两个基础状态就够了:
NORMAL:当前处于普通代码行,没有进入多行字符串IN_MULTILINE_STRING:当前正处于三引号包裹的多行字符串中
逐行处理逻辑
我们逐行读取输入,然后根据当前状态来处理每一行的内容,重点是跟踪三引号的出现位置,以及处理状态切换:
当处于 NORMAL 状态时
- 在当前行中寻找未被转义的第一个
"""(这里要注意,如果你的语言支持转义字符,比如\""",不能把它当作字符串的起始标记) - 如果没找到三引号:整行都是普通代码,直接交给普通代码处理逻辑即可
- 如果找到了三引号:
- 先处理三引号之前的普通代码部分
- 切换状态到
IN_MULTILINE_STRING - 继续从三引号结束的位置开始扫描剩余内容(如果同一行后面还有内容,比如
"""abc"""def,那后面的def要切回普通状态处理)
当处于 IN_MULTILINE_STRING 状态时
- 在当前行中寻找未被转义的
""" - 如果没找到:整行都是多行字符串的一部分,把它加入到字符串缓冲区中
- 如果找到了:
- 把当前行中三引号之前的部分加入缓冲区,然后将整个缓冲区的内容作为完整的多行字符串提交给处理逻辑
- 清空缓冲区,切换回
NORMAL状态 - 继续从三引号结束的位置扫描剩余内容,当作普通代码处理
伪代码示例
我写个类Python的伪代码,你可以直接参考这个逻辑来实现:
# 定义状态常量 STATE_NORMAL = 0 STATE_IN_MULTILINE = 1 # 全局状态和缓冲区 current_state = STATE_NORMAL multiline_buffer = [] def find_unescaped_triple_quote(s, start=0): """辅助函数:查找字符串中第一个未被转义的三引号""" pos = start str_len = len(s) while pos <= str_len - 3: if s[pos:pos+3] == '"""': # 统计前面的反斜杠数量,判断是否被转义 backslash_count = 0 check_pos = pos - 1 while check_pos >= 0 and s[check_pos] == '\\': backslash_count += 1 check_pos -= 1 # 偶数个反斜杠=未被转义 if backslash_count % 2 == 0: return pos pos += 1 return -1 def process_line(line): global current_state, multiline_buffer pos = 0 line_len = len(line) while pos < line_len: if current_state == STATE_NORMAL: quote_pos = find_unescaped_triple_quote(line, pos) if quote_pos == -1: # 处理剩余的普通代码 if pos < line_len: handle_normal_code(line[pos:]) pos = line_len else: # 处理三引号前的普通代码 if quote_pos > pos: handle_normal_code(line[pos:quote_pos]) # 切换到多行字符串状态 current_state = STATE_IN_MULTILINE pos = quote_pos + 3 # 跳过三引号 else: quote_pos = find_unescaped_triple_quote(line, pos) if quote_pos == -1: # 整行加入缓冲区(注意是否保留换行符,根据你的语言规范调整) multiline_buffer.append(line[pos:]) pos = line_len else: # 处理到闭合三引号前的字符串内容 multiline_buffer.append(line[pos:quote_pos]) # 提交完整的多行字符串 handle_multiline_string(''.join(multiline_buffer)) multiline_buffer = [] # 切换回普通状态 current_state = STATE_NORMAL pos = quote_pos + 3 # 跳过三引号 # 示例处理函数,根据你的需求替换成实际逻辑 def handle_normal_code(code): if code.strip(): print(f"[普通代码] {repr(code)}") def handle_multiline_string(s): print(f"[多行字符串] {repr(s)}")
额外注意事项
- 换行符处理:如果你的语言和Python一样,三引号字符串会保留换行符,那在把行内容加入缓冲区时,可能需要加上换行符(比如
multiline_buffer.append(line[pos:] + '\n')),具体看你的语言规范 - 转义字符:如果你的语言支持其他转义(比如
\n、\t),在处理多行字符串内容时,可能需要额外做转义解析 - 边缘情况:比如空行、一行内多个三引号嵌套(不过类Python的话,三引号字符串里直接写
"""是会闭合的,所以不需要处理嵌套,除非你的语言有特殊规则)
这个逻辑非常高效,完全符合逐行处理的约束,状态机的切换也很清晰,你可以根据自己的语言特性调整细节~
内容的提问来源于stack exchange,提问作者sciroccorics
相关产品推荐
相关产品推荐

