这里有一个类似的问题:Regular Expression For Consecutive Duplicate Words。这解决了如何解决这个问题的一般问题,而我正在寻找有关我的解决方案无效的具体建议。
我正在使用python正则表达式,我正在尝试匹配所有连续重复的单词,例如粗体:
我正在努力去使这个工作
我试过了:
text = "But then of course African swallows are nonmigratory"
def lenumerate(txt):
s = text.split(' ')
return list(zip(s, map(len, s)))
# [('But', 3), ('then', 4), ('of', 2), ('course', 6), ('African', 7),
# ('swallows', 8), ('are', 3), ('nonmigratory', 12)]
这是正则表达式选择背后的逻辑:[A-Za-z0-9]* {2}
应匹配任何长度的任何单词,'[A-Za-z0-9]*'
使其考虑单词末尾的空格。因此'[A-Za-z0-9]* '
应标记前一个单词的重复,并在末尾添加一个空格。换句话说,它说“对于任何一个词,找到在空格后立即重复的情况”。
我的逻辑在这里有什么缺陷?为什么这个正则表达式不起作用?
答案 0 :(得分:5)
[A-Za-z0-9]* {2}
正则表达式中的量词将始终仅适用于它们前面的元素。因此,\d+
会查找一个或多个数字,但x\d+
会查找单个 x
,后跟一个或多个数字。
如果您希望量词不仅适用于单一事物,则需要先对其进行分组,例如: (x\d)+
。这是一个捕获组,因此它实际上会在结果中捕获它。如果您只想将事物分组以应用通用量词,这有时是不受欢迎的。在这种情况下,您可以为群组添加?:
前缀,使其成为非捕获群组:(?:x\d)+
。
所以,回到你的正则表达式,你必须这样做:
([A-Za-z0-9]* ){2}
然而,这实际上并没有检查第二个匹配的单词是否与第一个相同。如果你想匹配,你需要使用反向引用。反向引用允许您在表达式中引用先前捕获的组,再次查找它。在您的情况下,这将是这样的:
([A-Za-z0-9]*) \1
\1
将引用第一个捕获组,即([A-Za-z0-9]*)
。所以小组将匹配第一个单词。然后,有一个空格,然后再次对第一个单词进行反向引用。因此,这将寻找由空格分隔的相同单词的重复。
正如博评泡泡在评论中指出的那样,仍有很多人可以做些改进正则表达式。虽然我主要关心的是解释各种概念而不过多关注你的特定例子,但我想我仍然欠你一个更健壮的正则表达式,用于匹配字符串中由空格分隔的两个连续单词。这是我对此的看法:
\b(\w+)\s\1\b
有一些与前一种方法不同的东西:首先,我正在寻找整个表达式的单词边界。 \b
基本上在单词开始或结束时匹配。这将阻止表达式在其他词语中匹配,例如, <{1}}和foo fooo
都不匹配。
然后,正则表达式需要至少一个字符。所以空话不会匹配。我也在这里使用foo oo
这是一种更灵活的方式来包含字母数字字符。最后,我不是寻找实际的空间,而是接受单词之间的任何空格,所以这甚至可以匹配制表符或换行符。在那里添加量词也是有意义的,即\w
允许多个空白字符。
当然,这对你来说效果更好,取决于你的实际要求,我们无法从你的一个例子中说出来。但是,这应该会给你一些关于如何至少继续的想法。
答案 1 :(得分:3)
您可以将先前的捕获组与第一组\1
匹配,第二组匹配\2
等等。
import re
s = "I am struggling to to make this this work"
matches = re.findall(r'([A-Za-z0-9]+) \1', s)
print(matches)
>>> ['to', 'this']
如果您想要两次出现,请在\1
附近添加一个捕获组:
matches = re.findall(r'([A-Za-z0-9]+) (\1)', s)
print(matches)
>>> [('to', 'to'), ('this', 'this')]
答案 2 :(得分:2)
一眼就看出这会匹配任何两个单词,而不是重复单词。如果我没记错,星号(*)会匹配零次或多次,所以也许你应该使用加号(+)表示一个或多个。然后,您需要提供捕获并重新使用捕获的结果。此外,为了清楚起见,\w
可用于字母数字字符。此外,\b
可用于匹配单词边界处的空字符串。
以下示例中的某些内容将帮助您完成部分工作。
>>> import re
>>> p = re.compile(r'\b(\w+) \1\b')
>>> p.findall('fa fs bau saa saa fa bau eek mu muu bau')
['saa']
这些页面可能会提供一些指导:
答案 3 :(得分:1)
这应该有效:\b([A-Za-z0-9]+)\s+\1\b
\b
匹配字边界,\s
匹配空格,\1
指定第一个捕获组。
>>> s = 'I am struggling to to make this this work'
>>> re.findall(r'\b([A-Za-z0-9]+)\s+\1\b', s)
['to', 'this']
答案 4 :(得分:1)
这是一个不使用RegEx的简单解决方案。
sentence = 'I am struggling to to make this this work'
def find_duplicates_in_string(words):
""" Takes in a string and returns any duplicate words
i.e. "this this"
"""
duplicates = []
words = words.split()
for i in range(len(words) - 1):
prev_word = words[i]
word = words[i + 1]
if word == prev_word:
duplicates.append(word)
return duplicates
print(find_duplicates_in_string(sentence))