我试过这段代码:
re.findall(r"d.*?c", "dcc")
搜索带有第一个字母d和最后一个字母c的子字符串。
但我得到输出['dc']
正确的输出应为['dc', 'dcc']
。
我做错了什么?
答案 0 :(得分:0)
使用我所知道的任何内置正则表达式函数,您所寻找的内容是不可能的。 re.findall()
仅返回非重叠匹配。在匹配dc
之后,它会在此之后查找另一个匹配项。由于字符串的其余部分仅为c
,并且不匹配,因此它已完成,因此只返回["dc"]
。
当您使用像*
这样的量词时,您可以选择让它变得贪婪或非贪婪 - 或者找到正则表达式的最长或最短匹配。要做你想做的事,你需要一种方法来告诉它连续寻找更长的匹配,直到它找不到任何东西。没有简单的方法可以做到这一点。您可以使用具有特定计数的量词,但您必须在代码中循环它:
d.{0}c
d.{1}c
d.{2}c
d.{3}c
...
如果你有一个包含多个量化子模式的正则表达式,你必须尝试所有长度组合。
答案 1 :(得分:0)
你的两个问题是.*
贪婪而.*?
是最小的,而re.findall()只返回非重叠的匹配。这是一个可能的解决方案:
def findall_inner(expr, text):
explore = list(re.findall(expr, text))
matches = set()
while explore:
word = explore.pop()
if len(word) >= 2 and word not in matches:
explore.extend(re.findall(expr, word[1:])) # try more removing first letter
explore.extend(re.findall(expr, word[:-1])) # try more removing last letter
matches.add(word)
return list(matches)
found = findall_inner(r"d.*c", "dcc")
print(found)
这有点过分,使用findall而不是搜索并使用>= 2
代替> 2
,因为在这种情况下,d.*c
只能有一个非重叠匹配并且单字符字符串与模式不匹配。但是它有一些灵活性取决于你可能想要的其他类型的模式。
答案 2 :(得分:-1)
试试这个正则表达式:
^d.*c$
基本上,您正在寻找字符串的开头为d,字符串的结尾为c。
答案 3 :(得分:-2)
这是一个非常重要的要点:正则表达式引擎始终返回最左边的匹配,即使是更好的"匹配可以在以后找到。将正则表达式应用于字符串时,引擎从字符串的第一个字符开始。它会在第一个字符处尝试正则表达式的所有可能排列。只有在尝试了所有可能性并且发现失败时,引擎才会继续使用文本中的第二个字符。因此,当它找到[' dc']然后引擎通过' dc'并继续第二个'。所以不可能与[' dcc']匹配。