簡體   English   中英

為什么這個正則表達式匹配兩個連續的單詞不起作用?

[英]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 fooofoo 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM