Python 后视正则表达式 "fixed-width pattern" 查找连续重复的词时出错
Python look-behind regex "fixed-width pattern" error while looking for consecutive repeated words
我有一个文本,其中的单词由 .
分隔,其中有 2 个和 3 个连续重复的单词:
My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die-
我需要用正则表达式独立匹配它们,排除一式三份中的重复项。
因为最多。 3个连续重复的单词,this
r'\b(\w+)\.+\.+\b'
成功捕获
father.father.father
但是,为了捕捉 2 个连续的重复词,我需要确保下一个词和上一个词不相同。我可以做一个负向预测
r'\b(\w+)\.+(?!\.+)\b'
但我在负面回顾
中的尝试
r'(?<!(\w)\.)\b\.+\b(?!\.)'
return 固定宽度问题(当我保留 +
时)或其他问题。
我应该如何纠正负面回顾?
我认为可能有一种更简单的方法来捕捉您想要的内容,而无需消极的回顾:
r = re.compile(r'\b((\w+)\.+\.+?)\b')
r.findall(t)
> [('name.name.', 'name'), ('father.father.father', 'father')]
只是将第三次重复设为可选。
一个版本可以捕获任意数量的同一个词的重复,看起来像这样:
r = re.compile(r'\b((\w+)(\.+)*)\b')
r.findall(t)
> [('name.name', 'name', '.name'), ('father.father.father', 'father', '.father')]
也许根本不需要正则表达式。
使用 itertools.groupby
就可以了。 设计 将连续项目的相等出现分组。
- 按词分组(按点拆分后)
- 转换为列表并发出一个
tuple
值,仅当长度> 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
我有一个文本,其中的单词由 .
分隔,其中有 2 个和 3 个连续重复的单词:
My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die-
我需要用正则表达式独立匹配它们,排除一式三份中的重复项。
因为最多。 3个连续重复的单词,this
r'\b(\w+)\.+\.+\b'
成功捕获
father.father.father
但是,为了捕捉 2 个连续的重复词,我需要确保下一个词和上一个词不相同。我可以做一个负向预测
r'\b(\w+)\.+(?!\.+)\b'
但我在负面回顾
中的尝试r'(?<!(\w)\.)\b\.+\b(?!\.)'
return 固定宽度问题(当我保留 +
时)或其他问题。
我应该如何纠正负面回顾?
我认为可能有一种更简单的方法来捕捉您想要的内容,而无需消极的回顾:
r = re.compile(r'\b((\w+)\.+\.+?)\b')
r.findall(t)
> [('name.name.', 'name'), ('father.father.father', 'father')]
只是将第三次重复设为可选。
一个版本可以捕获任意数量的同一个词的重复,看起来像这样:
r = re.compile(r'\b((\w+)(\.+)*)\b')
r.findall(t)
> [('name.name', 'name', '.name'), ('father.father.father', 'father', '.father')]
也许根本不需要正则表达式。
使用 itertools.groupby
就可以了。 设计 将连续项目的相等出现分组。
- 按词分组(按点拆分后)
- 转换为列表并发出一个
tuple
值,仅当长度> 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