2017-09-13 19 views
1

我很少使用| *之前。但是今天,當我將它們兩個都用在一起時,我發現一些結果令人困惑。我使用的表達式爲(在python)如下:替代匹配的行爲「|」與。*在正則表達式

>>> s = "abcdefg" 
>>> re.findall(r"((a.*?c)|(.*g))",s) 
[('abc',''),('','defg')] 

第一caputure的結果是所有的權利,但第二捕捉出乎我的意料,因爲我預計第二擷取將是「ABCDEFG」 (整個字符串)。

然後我扭轉兩種選擇:

>>> re.findall(r"(.*?g)|(a.*?c)",s) 
[('abcdefg', '')] 

看來,正則表達式引擎只讀取字符串一次 - 當在第一替代讀取整個字符串,正則表達式引擎將停止,不再檢查第二個選擇。但是,在第一種情況下,在處理第一種替代方案之後,正則表達式引擎僅從「a」讀取「c」,並且字符串中仍有「d」到「g」,與「。*?」匹配。克「在第二個選擇。我說得對嗎?更重要的是,對於有替代表達式的表達式,正則表達式引擎會首先檢查第一個替代方案,如果它匹配字符串,它將永遠不會檢查第二個替代方案。這是對的嗎?

此外,如果我想要像第一種情況一樣獲取「abc」和「abcdefg」或「abc」和「bcde」(兩個結果重疊),我應該使用什麼表達式?

非常感謝!

+0

你不能從正則表達式中的相同位置開始兩個匹配。 're.findall'將抓取字符串中所有不重疊的匹配項,並且由於第一個匹配項從頭開始,以'c'結尾,下一個匹配項只能在'defg'內的'c'之後找到。 –

+0

@cᴏʟᴅsᴘᴇᴇᴅ你知道,欺騙的原因是不正確的(這不是[捕獲組與findall?]的愚蠢?](https://stackoverflow.com/questions/6018340/capturing-group-with-findall)問題)。 –

+0

@WiktorStribiżew道歉,閱讀前幾句話並作出反應。 –

回答

1

您不能從正則表達式中的相同位置開始兩個匹配。

re.findall(r"((a.*?c)|(.*g))",s)re.findall會抓住所有非重疊的匹配字符串中,由於第一個在開始處開始,c結束,下一個只能c後發現,內defg

(.*?g)|(a.*?c)正則表達式匹配abcdefg因爲正則表達式引擎解析字符串由左到右,而.*?會得到什麼0+字符儘可能少,但到第一個g。而且,由於g是最後一個字符,它將匹配和捕獲整個串入組1

要獲得abcabcdefg,你可以使用,說

(a.*?c)?.*g 

regex demo

Python demo

import re 
rx = r"(a.*?c)?.*g" 
s = "abcdefg" 
m = re.search(rx, s) 
if m: 
    print(m.group(0)) # => abcdefg 
    print(m.group(1)) # => abc 

它可能不是你想要的東西,但它sh應該給你一個提示:你匹配較大的部分,並捕獲字符串的一個子部分。

+1

謝謝你的回答!我使用這個表達式是因爲我現在正在處理一個經典文本,每行(段落)都包含一些句子,括號中有註釋,有些沒有註釋。所以我使用r「(。*?)(\\(。*?\\))|(。*?)$」來抓住每行中有和沒有註釋的所有句子。其實我真的希望(。*?)$在第二個選擇中匹配字符串的其餘部分而不是整體,但我不知道它是否只是可能在某個地方被打破的巧合,或者它是內置的特徵。現在我知道這是一種我可以依賴的安全行爲。謝謝! – none

0

重新閱讀re.findall方法的文檔。 「

findall」返回字符串中模式的所有非重疊匹配項,作爲字符串列表。字符串從左到右掃描,匹配按照找到的順序返回。

具體而言,非重疊匹配,和從左到右。所以如果你有一個字符串abcdefg和一個模式將匹配abc,那麼任何其他模式必須(1)不重疊;和(2)更靠右。

根據說明匹配abcdefg是完全有效的。這將是一個錯誤,匹配abcabcdefg甚至abccdefg,因爲它們會重疊。

+0

你知道,'abc'和'abcdefg'重疊的事實並不重要,因爲重疊的字符串不能從相同的位置開始,可以使用lookahead在正則表達式中捕獲,但這裏的問題是它們從相同的位置開始位置在字符串中。 –

+0

現在我明白了!謝謝您的回答! – none