簡體   English   中英

標准正則表達式與python正則表達式之間的差異

[英]Standard Regex vs python regex discrepancy

我正在讀一本書,它們提供了一個如何將給定字符串與正則表達式匹配的示例。 這是他們的例子:

b*(abb*)*(a|∊) - Strings of a's and b's with no consecutive a's.

現在,我嘗試將其轉換為python,如下所示:

>> p = re.compile(r'b*(abb*)*(a|)') # OR
>> p = re.compile(r'b*(abb*)*(a|\b)')

# BUT it still doesn't work
>>> p.match('aa')
<_sre.SRE_Match object at 0x7fd9ad028c68>

我的問題有兩個:

  1. 使上面的示例正常工作,python中的epsilon等效於什么?
  2. 有人可以向我解釋為什么做正則表達式的理論或標准方法在python中不起作用嗎? 最長匹配與最短匹配可能有關嗎?

澄清:對於那些問什么標准正則表達式的人-這是形式語言理論標准: http : //en.wikipedia.org/wiki/Regular_expression#Formal_language_theory

實際上,該示例工作得很好……只是一個很小的細節。 我會寫:

>>> p = re.compile('b*(abb*)*a?')
>>> m = p.match('aa')
>>> print m.group(0)
'a'
>>> m = p.match('abbabbabababbabbbbbaaaaa')
>>> print m.group(0)
abbabbabababbabbbbba

請注意,組0返回與正則表達式匹配的字符串部分。

如您所見,該表達式匹配連續的a和b,而不重復a。 如果確實要檢查整個字符串,則需要稍作更改:

>>> p = re.compile('^b*(abb*)*a?$')
>>> m = p.match('aa')
>>> print m
None

^$強制識別字符串的開頭和結尾。

最后,您可以使用第一個正則表達式來組合這兩種方法,但最后要進行測試:

>>> len(m.group(0)) == len('aa')

補充:對於OT的第二部分,在我看來,標准正則表達式與python實現之間沒有差異。 當然,表示法略有不同,並且python實現建議了一些擴展(與大多數其他軟件包一樣)。

感謝您的回答。 我覺得每個答案都有一部分答案。 這是我一直在尋找的東西。

  1. 符號只是(something |ε)的簡寫。 因此(a |ε)可以改寫為a? 因此,示例變為:

     b*(abb*)*a? 

    在python中,我們將編寫:

     p = re.compile(r'^b*(abb*)*a?$') 
  2. 將正則表達式語法直接轉換為python(即復制和粘貼)不起作用的原因是,因為python匹配最短的子字符串 (如果沒有$或^符號),而理論上的正則表達式匹配最長的初始子字符串
    例如,如果我們有一個字符串:

     s = 'aa' 

    我們的教科書正則表達式b *(abb *)* a? 不會匹配,因為它有兩個a。 但是,如果我們直接將其復制到python:

     >> p = re.compile(r'b*(abb*)*a?') >> bool(p.match(s)) True 

    這是因為我們的正則表達式僅匹配字符串“ aa”的子字符串“ a”。
    為了告訴python在整個字符串上進行匹配,我們必須告訴它字符串的開頭和結尾在哪里,分別用^$符號:

     >> p = re.compile(r'^b*(abb*)*a?$') >> bool(p.match(s)) False 

    請注意,python regex match()在字符串的開頭匹配,因此它會自動在開頭假設^ 但是search()函數沒有,因此我們保留^
    因此,例如:

     >> s = 'aa' >> p = re.compile(r'b*(abb*)*a?$') >> bool(p.match(s)) False # Correct >> bool(p.search(s)) True # Incorrect - search ignored the first 'a' 

1個

  • 使用bool(p.match('aa'))檢查正則表達式是否匹配

  • p = re.compile('b*(abb*)*a?$')

  • \\b匹配字符串的邊框; \\w\\W之間的位置(單詞字符和非單詞字符)

2

正則表達式在python中是非常標准的。 但是每種語言都有它們的風格,它們不是100%可移植的。 在使用任何特定語言的regexp之前,您應該先查找一些細微的差異。

加成

\\epsilon在python中沒有特殊符號。 它是一個空字符集。

在您的示例中a|\\epsilon等效於(a|)或只是a? 之后, $必須匹配字符串的結尾。

我不完全確定match如何在python中工作,但我認為您可能需要在您的RE中添加^ .... $。 RegExp匹配通常匹配子字符串,並且在p.match('aa')為“ a”(可能是第一個)的情況下找到最大的匹配項。 ^ ... $確保您匹配整個字符串,我相信這是您想要的。

理論/標准正則表達式假定您始終匹配整個字符串,因為您使用它來定義匹配的字符串語言,而不是在輸入字符串中找到子字符串。

之所以匹配,是因為您的正則表達式匹配任何標本文本的任何零寬度段。 您需要錨定正則表達式。 這是一種使用零寬度超前斷言的方法:

re.compile(r'^(a(?!a)|b)*$')

據我所知,您的第二個回答應該是epsilon的合適替代品,盡管我以前從未在正則表達式中見過epsilon。

無論值多少,您的模式都匹配“ a”。 也就是說,它是匹配的:

  • 零個或多個“ b ”(選擇零)
  • 零個或多個“ (abb*) ”(選擇零)
  • 一個“ a ”或單詞結尾(選擇a)。

正如喬納森·費恩伯格(Jonathan Feinberg)指出的那樣,如果要確保整個字符串匹配,則必須錨定正則表達式的開頭( '^' )和結尾( '$' )。 每當在python中構造正則表達式時,也應使用原始字符串:r'my regex'。 這樣可以防止過多的反斜杠避免混淆。

表達式的問題在於它與空字符串匹配,這意味着如果您這樣做:

>>> p = re.compile('b*(abb*)*(a|)')
>>> p.match('c').group(0)
''

並且由於re.match嘗試匹配字符串的開頭,因此您必須告訴它匹配它直到字符串的結尾。 只需使用$

>>> p = re.compile(r'b*(abb*)*(a|)$')
>>> print p.match('c')
None
>>> p.match('ababababab').group(0)
'ababababab'

ps-您可能已經注意到,我在此處更多使用r'pattern'而不​​是'pattern'(第一段)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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