在Python中使用RE库拆分字符串,如何保留标点符号和其他非字母数字字符

2024-06-09 02:32:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我想模拟编译器的扫描器和解析器阶段。我试着用

    re.findall(r"[\w,.,\"]+",file)

如果文件包含:

INT x;
READ x;
x := (x+1)*x;
WRITE x

结果是:

['INT', 'x', 'READ', 'x', 'x', 'x', '1', 'x', 'WRITE', 'x']

但是我需要;和+和()等等。。。我如何分割文字却保留字符??谢谢

这应该是输出:

['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=',  '(','x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']

Tags: 文件re解析器read编译器字符阶段file
3条回答

最简单(几乎正确)的代码应该是:

import re

source = """
INT x;
READ x;
x := (x+1)*x;
WRITE x
"""
print(re.findall(r'\w+|[^\s\w]+', source)

输出:

['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=', '(', 'x', '+', '1', ')*', 'x', ';', 'WRITE', 'x']

但是,只要不明确定义语言中的所有运算符,就没有解决方案来区分正确的多字符运算符(例如:=)和串联的单字符运算符序列(例如)*)。因此,使用真正的解析器将更容易,例如任务。你知道吗

编辑(评论后):

regex主要搜索两种类型的序列:一个或多个连续的字母数字字符(由\w+表示)或一个或多个非字母数字和非空格的连续字符(由[^\w\s]+表示)。你知道吗

这是我能想到的最好的办法:

import re

test_str = "INT x; READ x; x := (x+1)*x; WRITE x"
test_reg_pat = "([A-Z]+)|([x])|([^ ])"

test_list = re.findall(test_reg_pat,test_str)


ret_list = []

for sub_list in test_list:
  for elem in sub_list:
    if elem != '':
      ret_list.append(elem)


print(ret_list)

其中ret_list的输出是:

['INT', 'x', ';', 'READ', 'x', ';', 'x', ':', '=', '(', 'x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']

可能有一种方法可以完全用regex来实现这一点,而不必将test_list处理成ret_list我是如何做到的。最大的问题是,将re.findall()与组一起使用(我在模式中使用的方法)将返回一个包含任何匹配项的子列表给组,如下所示:

[('INT', '', ''), ('', 'x', ''), ('', '', ';'), ('READ', '', ''), ('', 'x', ''), ('', '', ';'), ('', 'x', ''), ('', '', ':'), ('', '', '='), ('', '', '('), ('', 'x', ''), ('', '', '+'), ('', '', '1'), ('', '', ')'), ('', '', '*'), ('', 'x', ''), ('', '', ';'), ('WRITE', '', ''), ('', 'x', '')]

希望它有帮助-如果你需要它与纯regex让我知道,我可以看看我是否可以解决一些问题!你知道吗

您可以尝试非常明确地说明要匹配的内容,其中input是您的输入字符串:

re.findall(r"\w+|:=|[\w()*+;]", input)

这应该给出您要查找的确切输出:

['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=', '(', 'x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']

相关问题 更多 >