Python - 查找所有出现的子字符串(包括重叠)?

时间:2013-09-21 14:22:43

标签: python regex string substring

好的,我发现了这个:Find all occurrences of a substring in Python

其中说,为了使索引重叠列表中的子串的出现,您可以使用:

[m.start() for m in re.finditer('(?=SUBSTRING)', 'STRING')]

哪个有效,但我的问题是要查找的字符串和子字符串都是由变量定义的。我不太了解正则表达式知道如何处理它 - 我可以使用非重叠的子串,这只是:

[m.start() for m in re.finditer(p3, p1)]

感谢。

编辑:

因为有人问,我会继续进行说明。 p1和p3可以是任何字符串,但如果是,例如p3 = "tryt"p1 = "trytryt",则结果应为[0, 3]

3 个答案:

答案 0 :(得分:7)

re.finditer的参数是简单的字符串。如果变量中有子字符串,只需将其格式化为正则表达式即可。像'(?={0})'.format(p3)之类的东西就是一个开始。由于RE中的various symbols do have special meaning,您将要逃避它们。幸运的是,re module包括re.escape以满足这种需求。

[m.start() for m in re.finditer('(?={0})'.format(re.escape(p3)), p1)]

答案 1 :(得分:1)

正则表达式在这里可能有点矫枉过正:

>>> word = 'tryt'
>>> text = 'trytryt'
>>> [i for i, _ in enumerate(text) if text.startswith(word, i)]
[0, 3]

答案 2 :(得分:0)

您正在执行此操作(或语法变体):

import re

needle = "(?=(aba))"
haystack = "ababababa"

[match.start() for match in re.finditer(needle, haystack)]
#>>> [0, 2, 4, 6]

应该有用。

因此问题可能是needle不是正确的形式,“(?=(...))”,(这与你与D.Shawley的互动很明显)。在这种情况下,有几种选择。

如果您的子字符串是有效的正则表达式,您可以手动迭代可能的位置,进行匹配。

needle = re.compile(needle)
[i for i in range(len(haystack)) if needle.match(haystack, i)]
#>>> [0, 2, 4, 6]

如果你不想要任意的正则表达式而只需要精确的子字符串匹配,那么完全避免使用正则表达式会更加清晰:

needle = "aba"
haystack = "ababababa"

[i for i in range(len(haystack)) if haystack.startswith(needle, i)]
#>>> [0, 2, 4, 6]

如果您正在寻找更快的结果,可以展开循环并使用.index加快搜索速度:

def findall(needle, haystack):
    i = 0
    try:
        while True:
            i = haystack.index(needle, i)
            yield i
            i += 1

    except ValueError:
        pass

这是我能想到的最快的方法。