我有一个像"F(230,24)F[f(22)_(23);(2)%[+(45)FF]]"
这样的字符串,除括号和括号外的每个字符代表一种指令。字符后面可以跟随可选括号中指定的可选参数列表。
这样的字符串我想把字符串拆分成
['F(230,24)', 'F', '[', 'f(22)', '_(23)', ';(2)', '%', '[', '+(45)', 'F', 'F', ']', ']']
,但目前我只获得['F(230,24)', 'F', '[', 'f(22)_(23);(2)', '%', '[', '+(45)', 'F', 'F', ']', ']']
(子字符串未正确分割)。
目前我正在使用list(filter(None, re.split(r'([A-Za-z\[\]\+\-\^\&\\\/%_;~](?!\())', string)))
,这只是一堆字符和(
的负面预测。 list(filter(None, <list>))
用于从结果中删除空字符串。
我知道这可能是因为Python的re.split
被设计为不分割为零长度匹配as discussed here。
但是我想知道什么是一个好的解决方案?有没有比re.findall
更好的方式?
谢谢。
编辑:很遗憾,我不允许使用regex
module
答案 0 :(得分:2)
我知道这可能是因为Python的re.split被设计为不分割为零长度匹配
您可以使用regex
module的VERSION1
标记。从你已链接的主题中取that example - 看看split()
如何产生零宽度匹配:
>>> import regex as re
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1)
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']
答案 1 :(得分:2)
您可以使用re.findall
找出所有单个字符,后面跟一对括号:
import re
s = "F(230,24)F[f(22)_(23);(2)%[+(45)FF]]"
re.findall("[^()](?:\([^()]*\))?", s)
['F(230,24)',
'F',
'[',
'f(22)',
'_(23)',
';(2)',
'%',
'[',
'+(45)',
'F',
'F',
']',
']']
[^()]
匹配除括号外的单个字符; (?:\([^()]*\))?
表示由一对括号括起来的非捕获组(?:
),并使用?
使该组可选; 答案 2 :(得分:1)
另一种解决方案。这次模式识别结构为 SYMBOL [(NUMBER [,NUMBER ...])] 的字符串。函数parse_it
返回 True ,如果字符串与正则表达式匹配,则返回标记, False ,如果不匹配则返回空白。
import re
def parse_it(string):
'''
Input: String to parse
Output: True|False, Tokens|empty_string
'''
pattern = re.compile('[A-Za-z\[\]\+\-\^\&\\\/%_;~](?:\(\d+(?:,\d+)*\))?')
tokens = pattern.findall(string)
if ''.join(tokens) == string:
res = (True, tokens)
else:
res = (False, '')
return res
good_string = 'F(230,24)F[f(22)_(23);(2)%[+(45)FF]]'
bad_string = 'F(2a30,24)F[f(22)_(23);(2)%[+(45)FF]]' # There is an 'a' in a bad place.
print(parse_it(good_string))
print(parse_it(bad_string))
<强>输出:强>
(正确,['F(230,24)','F','[','f(22)','_(23)',';(2)','%',' [”, '+(45)','F','F',']',']'])
(假,'')