Python 如何使用regexp拆分字符串而不保留捕获组?

Python 如何使用regexp拆分字符串而不保留捕获组?,python,regex,string,python-3.x,regex-group,Python,Regex,String,Python 3.x,Regex Group,我想在Python中使用带反向引用的正则表达式拆分文本 rexp = re.compile(r"([`]{1,})ABC\1") rexp.split("blahblah``ABC``blahblah") 我得到了['blahblah','blahblah','blahblah'],但预期['blahblah','blahblah']。 如何在不保留捕获组的情况下拆分字符串?来自文档: 如果模式中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回 由于您希望使用反向引用,您无法

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

rexp = re.compile(r"([`]{1,})ABC\1")
rexp.split("blahblah``ABC``blahblah")
我得到了
['blahblah','blahblah','blahblah']
,但预期
['blahblah','blahblah']
。 如何在不保留捕获组的情况下拆分字符串?

来自文档:

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

由于您希望使用反向引用,您无法避免第一个捕获组,但您可以将其余组设置为非捕获组,并对您的拆分进行后期处理,以获得您想要的内容,例如:

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

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

由于您希望使用反向引用,您无法避免第一个捕获组,但您可以将其余组设置为非捕获组,并对您的拆分进行后期处理,以获得您想要的内容,例如:

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

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

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

更新 显示这一点的时间与公认的答案一样快:

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)))
使用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

所以我不确定你所说的非常大的输入字符串是什么意思,这是一个可怕的成本…--计时显示,即使输入的字符串很大,它也一样或更快。

您可以先用唯一的分隔符替换拆分模式,然后在此基础上拆分:

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

更新 显示这一点的时间与公认的答案一样快:

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)))
使用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

所以我不确定你所说的非常大的输入字符串是什么意思,这是一个可怕的成本…--计时显示,即使输入字符串很大,它也一样或更快。

@GarbageCollector但由于反向引用,我不能使用非捕获组。@GarbageCollector但由于反向引用,我不能使用非捕获组。使其他非捕获组变得非常简单,谢谢!使其他组不捕获使此问题变得非常简单,谢谢!它不会比使用类似正则表达式的re.split更糟糕。见计时。。。在PyPy上,它非常快,不会比使用类似正则表达式的re.split更糟糕。见计时。。。在PyPy上,速度要快得多