如何在不保留捕获组的情况下使用正则表达式拆分字符串?

问题描述 投票:1回答:2

我想在Python中使用带有反向引用的正则表达式来分割文本。

rexp = re.compile(r"([`]{1,})ABC\1")
rexp.split("blahblah``ABC``blahblah")

我得到了['blahblah', '``', 'blahblah'],但预计['blahblah', 'blahblah']。如何在不保留捕获组的情况下拆分字符串?

python regex string python-3.x regex-group
2个回答
2
投票

来自re.split()文档:

如果在模式中使用捕获括号,则模式中所有组的文本也将作为结果列表的一部分返回。

由于你想使用反向引用,你无法避免第一个捕获组,但你可以让其余的捕获组不进行捕获并对你的拆分进行后处理以获得你想要的东西,例如:

rexp = re.compile(r"([`]{1,})->\s*(?:\S+)\s*\|(?:.+?)<-\1")
rexp.split("blahblah``->Left|Right<-``blahblah")[0::2]  # ['blahblah', 'blahblah']

更新:我刚刚注意到你在此期间改变了你的模式,但原理是一样的:

rexp = re.compile(r"([`]{1,})ABC\1")  # also, if optimizing, equivalent to: (`+)ABC\1
rexp.split("blahblah``ABC``blahblah")[0::2]  # ['blahblah', 'blahblah']

1
投票

您可以先使用唯一分隔符替换拆分模式,然后拆分:

>>> s="blahblah``ABC``blahblah"
>>> delim="<-split->"
>>> re.split(delim, re.sub(r"([`]+)ABC\1", delim, s))
['blahblah', 'blahblah']

这种方法的优点是您不需要假设分割模式在字符串中的位置。

然后,您可以使用更快的Python拆分,因为您已将正则表达式目标转换为固定字符串:

>>> re.sub(r"([`]+)ABC\1", delim, s).split(delim)
['blahblah', 'blahblah']

Update

显示时间的时间与接受的答案一样快:

import re

def f1(s):
    rexp = re.compile(r"([`]{1,})ABC\1")
    return rexp.split(s)[0::2]

def f2(s):
    delim="<-split->"  
    rexp1=re.compile(r"([`]+)ABC\1")  
    rexp2=re.compile(delim)
    return rexp2.split(rexp1.sub(delim, s))

def f3(s):
    delim="<-split->"  
    rexp=re.compile(r"([`]+)ABC\1")  
    return rexp.sub(delim, s).split(delim) 

if __name__=='__main__':
    import timeit    
    for case, x in (('small',1000),('med',10000),('large',1000000)):  
        s="blahblah``ABC``blahblah"*x
        print("Case {}, {:,} x, All equal: {}".format(case,x,(f1(s)==f2(s)==f3(s))))
        for f in (f1,f2,f3):
            print("   {:^10s}{:.4f} secs".format(f.__name__, timeit.timeit("f(s)", setup="from __main__ import f, s", number=10)))

在我的旧版iMac上,Python 3.6打印:

Case small, 1,000 x, All equal: True
       f1    0.0049 secs
       f2    0.0048 secs
       f3    0.0045 secs
Case med, 10,000 x, All equal: True
       f1    0.0512 secs
       f2    0.0536 secs
       f3    0.0526 secs
Case large, 1,000,000 x, All equal: True
       f1    5.2092 secs
       f2    5.6808 secs
       f3    5.5388 secs

使用PyPy,以我建议的方式执行它会更快:

Case small, 1,000 x, All equal: True
       f1    0.0020 secs
       f2    0.0021 secs
       f3    0.0012 secs
Case med, 10,000 x, All equal: True
       f1    0.0325 secs
       f2    0.0288 secs
       f3    0.0217 secs
Case large, 1,000,000 x, All equal: True
       f1    4.4900 secs
       f2    3.0680 secs
       f3    2.1079 secs

所以不确定你对于非常大的输入字符串是什么意思,这是一个可怕的成本...... - 时间显示即使使用巨大的输入字符串它也是相同或更快。

© www.soinside.com 2019 - 2024. All rights reserved.