[英]Why does this regular expression to match two consecutive words not work?
這里有一個類似的問題: 連續重復單詞的正則表達式 。 這解決了如何解決這個問題的一般問題,而我正在尋找有關我的解決方案不起作用的具體建議。
我正在使用python正則表達式,我正在嘗試匹配所有連續重復的單詞,例如粗體:
我努力使 這一這項工作
我試過了:
[A-Za-z0-9]* {2}
這是正則表達式選擇背后的邏輯: '[A-Za-z0-9]*'
應匹配任何長度的任何單詞, '[A-Za-z0-9]* '
使其考慮空間這個詞的結尾。 因此, [A-Za-z0-9]* {2}
應標記前一個字的重復,並在末尾添加一個空格。 換句話說,它說“對於任何一個詞,找到一個空格后立即重復的情況”。
我的邏輯在這里有什么缺陷? 為什么這個正則表達式不起作用?
[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
基本匹配。 這將阻止表達式在其他詞語中匹配,例如, foo fooo
和foo oo
都不匹配。
然后,正則表達式至少需要一個字符。 所以空話不會匹配。 我也在這里使用\\w
這是一種包含字母數字字符的更靈活的方式。 最后,我不是尋找實際的空間,而是接受單詞之間的任何空格,所以這甚至可以匹配制表符或換行符。 在那里添加量詞也是有意義的,即\\s+
允許多個空白字符。
當然,這對你來說效果更好,取決於你的實際要求,我們將無法從你的一個例子中說出來。 但這應該給你一些關於如何至少繼續的想法。
您可以將先前的捕獲組與\\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')]
一眼就看出這將匹配任何兩個單詞,而不是重復的單詞。 如果我沒記錯,星號(*)會匹配零次或多次,所以也許你應該使用加號(+)表示一個或多個。 然后,您需要提供捕獲並重新使用捕獲的結果。 此外,為了清楚起見, \\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']
這些頁面可能會提供一些指導:
這應該有效: \\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']
這是一個不使用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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.