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

时间:2018-04-23 20:03:47

标签: python regex

我想模拟编译器的扫描程序和解析器阶段。我设法使用

拆分
    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']

3 个答案:

答案 0 :(得分:1)

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

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']

但是,只要您没有明确定义您的语言的所有运算符,就没有解决方案来区分正确的多字符运算符(例如:=)与单字符运算符的连接序列(例如)*。因此,使用真正的解析器对任务来说会更容易。

编辑(评论后):

正则表达式基本上搜索两种类型的序列:一个或多个连续的字母数字字符(由\w+表示)或一个或多个非字母数字和非空格的连续字符(表示由[^\w\s]+)。

答案 1 :(得分:0)

这是我能想到的最好的:

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']

可能有一种方法可以完全使用正则表达式执行此操作,而无需将test_list处理为ret_list我是如何做到的。最大的问题是将re.findall()与组(我在我的模式中使用的)一起使用的是它将返回一个子列表,其中包含与该组匹配的任何内容,如下所示:

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

希望它有所帮助 - 如果您需要纯正的正则表达式让我知道,我可以看看我是否可以解决问题!

答案 2 :(得分:0)

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

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

这应该提供您正在寻找的确切输出:

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