Python后视正则表达式"固定宽度模式"寻找连续重复的单词时出错

时间:2017-07-26 18:10:39

标签: python regex regex-lookarounds negative-lookahead

我的文字包含.分隔的单词,其中包含2个和3个连续重复单词的实例:

My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die-

我需要将它们与正则表达式独立匹配,不包括重复的重复项。

因为有最大值连续3个重复的单词,这个

r'\b(\w+)\.+\1\.+\1\b'

成功捕获

father.father.father

但是,为了捕获连续2个重复的单词,我需要确保下一个和前一个单词不相同。我可以做一个负面预测

r'\b(\w+)\.+\1(?!\.+\1)\b'

但是我尝试了负面观察

r'(?<!(\w)\.)\b\1\.+\1\b(?!\.\1)'

要么返回固定宽度问题(当我保留+时),要么返回其他问题。

我应该如何纠正负面观察

2 个答案:

答案 0 :(得分:3)

我认为可能有一种更简单的方法来捕捉你想要的东西,而没有负面的背后隐藏:

r = re.compile(r'\b((\w+)\.+\2\.+\2?)\b')
r.findall(t)

> [('name.name.', 'name'), ('father.father.father', 'father')]

只需将第三次重复作为选择。

用于捕获同一个单词的任意数量重复的版本可以看起来像这样:

r = re.compile(r'\b((\w+)(\.+\2)\3*)\b')
r.findall(t)
> [('name.name', 'name', '.name'), ('father.father.father', 'father', '.father')]

答案 1 :(得分:3)

根本不需要正则表达式。

使用itertools.groupby完成这项工作。

  • 按字分组(按点分割后)
  • 转换为列表并发出tuple值,仅在长度&gt;时计数1
像这样:

import itertools

s = "My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die"

matches = [(l[0],len(l)) for l in (list(v) for k,v in itertools.groupby(s.split("."))) if len(l)>1]

结果:

[('name', 2), ('father', 3)]

所以基本上我们可以用这个元组列表做任何我们想做的事情(例如,根据出现次数对其进行过滤)

奖金(因为我一开始误读了这个问题,所以我把它留在了里面):从句子中删除重复的内容 - 按照上面的单词分组(按照点分割) - 仅获取列表comp中返回的值的键(值)(因为我们不计算,所以我们不需要这些值) - 用点

加入

在一行中(仍使用itertools):

new_s = ".".join([k for k,_ in itertools.groupby(s.split("."))])

结果:

My.name.is.Inigo.Montoya.You.killed.my.father.Prepare.to.die