只有当匹配组与其他匹配组不同的时候才匹配

4
我想使用正则表达式匹配每个以 w 开头并以 d 结尾的子字符串。
例如,对于输入 worldworld ,它应该返回 ('worldworld', 'world', 'world')。(注意:有两个 world,但它们是不同的,因为它们在字符串中的位置不同)
为此,我用以下正则表达式编写了这个程序:https://regex101.com/r/P9rUqU/2/
import re

s = '''worldworld'''

for g in re.finditer(r'(?=(w.*d))(?=(w.*?d))', s):
    print(g.start(1), g.end(1), g[1])
    print(g.start(2), g.end(2), g[2])
    print('-' * 40)

这将打印:

0 10 worldworld
0 5 world
----------------------------------------
5 10 world
5 10 world
----------------------------------------

它可以找到所有的子字符串,但有些是重复的(请注意组的起始和结束位置)。
我可以根据组的起始和结束位置筛选组,但我想知道是否可以通过更改正则表达式来仅返回唯一组。
我能否更改这个正则表达式以仅匹配与其他不同的组?如果可以,如何进行更改?我可以接受如何解决这个问题的建议。

在您所期望的输出中,有('worldworld','world','world'),但是您又声明不想要重复项。这到底是哪一个? - Paolo
@UnbearableLightness 子字符串位置的重复。 - Andrej Kesely
测试字符串 wdddd 显示另一个问题(它永远不会匹配 wddwddd 前缀)。改用一对嵌套的 string.find() 循环,如何? - Tim Peters
1
你不能仅仅依赖于 .*.*?。那么 worldworldworld 呢?我猜你期望匹配所有的组合,对吗?我认为这不是正则表达式最好的应用场景。 - 41686d6564 stands w. Palestine
@AhmedAbdelhameed 是的,所有子字符串的组合。我在思考这个问题,但是也许正则表达式并不适合它。 - Andrej Kesely
@TimPeters 是的,你说得对。也许正则表达式并不适合它。 - Andrej Kesely
2个回答

4

我不认为这可以通过单个正则表达式完成。但是使用嵌套循环很简单:

import re
test = "wddddd"
# need to compile the tail regexp to get a version of
# `finditer` that allows specifying a start index
tailre = re.compile("(d)")
for wg in re.finditer("(w)", test):
    start = wg.start(1)
    for dg in tailre.finditer(test, wg.end(1)):
        end = dg.end(1)
        print(test[start : end], "at", (start, end))

这会显示:

wd at (0, 2)
wdd at (0, 3)
wddd at (0, 4)
wdddd at (0, 5)
wddddd at (0, 6)

使用

test = "worldworldworld"

相反地:

world at (0, 5)
worldworld at (0, 10)
worldworldworld at (0, 15)
world at (5, 10)
worldworld at (5, 15)
world at (10, 15)

谢谢你的回答。是的,重复的链接告诉我单个正则表达式无法实现。我不知道你可以在正则表达式对象中加入“start”,今天我学到了 :) - Andrej Kesely
是的 - 许多正则表达式(和字符串)方法允许指定切片索引。这可以使一些看似棘手的任务变得简单高效(当然,在底层并没有提取任何切片 - 索引只是告诉方法从哪里开始(和停止)查找)。 - Tim Peters

1
一种选项是,对于懒惰的第二组,可以使用正向预查来匹配后面的.*d(贪婪模式),以确保如果懒惰的第二组匹配成功,它与贪婪的第一组不同:
(?=(w.*d))(?:(?=(w.*?d)(?=.*d)))?

https://regex101.com/r/UI9ds7/2


1
正如上面的评论所解释的那样,这对于 worldworldworld 不起作用。 - 41686d6564 stands w. Palestine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接