鉴于这种分号分离的C / Java /其他表达式
text = "func(10+3,40+5);....;func(6+7,8+9)"
我想提取由{2}添加的func
参数的位置。
import re
text = "func(10+3,40+5);....;func(6+7,8+9)"
result = [(x.start(),x.end()) for x in re.finditer("\d+\+\d+,?",text)]
print(result)
给出:
[(5, 10), (10, 14), (26, 30), (30, 33)]
但这不是我想要的:我想在参数不是连续时停止迭代(因为我稍后会寻找下一个func
,我想要提取func
的参数,而不是其他函数。
在这种情况下,re.finditer
会扭曲到下一个模式,跳过两者之间的不匹配数据。
为了做我想做的事,我想出了一个记忆上一场比赛并检查当前比赛是否就在它之后(如果存在)的解决方案。像这样:
result=[]
previous_match = None
for x in re.finditer("\d+\+\d+,?",text):
if previous_match and previous_match.end()!=x.start():
break
previous_match = x
result.append((x.start(),x.end()))
print(result)
给出:
[(5, 10), (10, 14)]
是我想要的东西,但是我失去了列表理解,并且我引入了一个丑陋的内存参数。有没有更好的方法呢?
答案 0 :(得分:2)
只是把我的两分钱放进去:用两个正则表达式会不会容易多了?
import re
text = "func(10+3,40+5,1002+54);....;func(6+7,8+9)"
func = re.compile(r'func\([^()]+\)')
params = re.compile(r'\d+\+\d+,?')
result = [[p.group(0) for p in params.finditer(f.group(0))] for f in func.finditer(text)]
print(result)
# [['10+3,', '40+5,', '1002+54'], ['6+7,', '8+9']]
这样每个元素只包含一个函数的参数
<小时/> 要获得这些头寸,我们需要将外部起始位置添加为偏移量:
import re
text = "func(10+3,40+5,1002+54);....;func(6+7,8+9)"
func = re.compile(r'func\([^()]+\)')
params = re.compile(r'\d+\+\d+,?')
result = [[(p.start() + f.start(), p.end() + f.start())
for p in params.finditer(f.group(0))]
for f in func.finditer(text)]
print(result)
# [[(5, 10), (10, 15), (15, 22)], [(34, 38), (38, 41)]]
答案 1 :(得分:1)
有正则表达式引擎支持\G
锚点,它匹配最后一个匹配的位置,但是python的re
模块没有。
如果您使用支持\G
锚点的regex module,则可以使用纯正则表达式解决方案。由于\G
仅匹配上一个匹配或字符串的开头(但我们的第一个结果 not 出现在字符串的开头),我们使用\G(?:^func\()?\K
来匹配字符串开头的func(
,然后将其丢弃:
import regex
for match in regex.finditer(r'\G(?:^func\()?\K\d+\+\d+,?', text):
print(match.span())
否则你将不得不求助于编写一些python代码。最简单的方法是搜索字符串,直到第一个“;”字符:
import re
for match in re.finditer(r'\d+\+\d+,?', text[:text.find(';')]):
print(match.span())
答案 2 :(得分:0)
您是否尝试将iter
与列表一起使用?
import re
text = "func(10+3,40+5);....;func(6+7,8+9)"
result = iter([(x.start(),x.end()) for x in re.finditer("\d+\+\d+,?",text)])
答案 3 :(得分:0)
正如评论所指出的那样,re
模块没有额外的逻辑(我已经想到),这是不可能的,所以我必须升级到regex
模块。
Stefan在评论中提供了一个答案,允许继续使用列表理解,因为它不需要任何标志。 Stephan建议在行上使用str.split(" ")[0]
来摆脱尾随函数,我更喜欢使用str.partition(";")[0]
,因为这是代码所以函数调用已经以;
结束(如果它在下一行,它并不重要)
result = [(x.start(),x.end()) for x in re.finditer("\d+\+\d+,?",text.partition(";")[0])]
作为奖励,partition
略快于split
,即使它创建了3个字符串,与纯正的正则表达式解决方案相比,它没有创建字符串来抛出它们,这有点浪费程。