簡體   English   中英

Python 正則表達式是否等同於 Ruby 的原子分組?

[英]Do Python regular expressions have an equivalent to Ruby's atomic grouping?

Ruby 的正則表達式有一個稱為原子分組(?>regexp)的功能,如這里所述,Python 的re模塊中是否有任何等效項?

Python不直接支持這個功能,但您可以使用零寬度前瞻斷言( (?=RE) )來模擬它,它從當前點匹配您想要的相同語義,放置一個命名組( (?P<name>RE)在前瞻中, (?P<name>RE) )然后使用命名的反向引用( (?P=name) )來匹配零寬度斷言匹配的任何內容。 結合在一起,這將為您提供相同的語義,代價是創建一個額外的匹配組,以及許多語法。

例如,您提供的鏈接給出了Ruby示例

/"(?>.*)"/.match('"Quote"') #=> nil

我們可以在Python中仿效:

re.search(r'"(?=(?P<tmp>.*))(?P=tmp)"', '"Quote"') # => None

我們可以證明我正在做一些有用的事情而不僅僅是噴出線噪聲,因為如果我們改變它以使內部組不吃最后的" ,它仍然匹配:

re.search(r'"(?=(?P<tmp>[A-Za-z]*))(?P=tmp)"', '"Quote"').groupdict()
# => {'tmp': 'Quote'}

您還可以使用匿名組和數字反向引用,但這會非常充滿線噪聲:

re.search(r'"(?=(.*))\1"', '"Quote"') # => None

(完全披露:我從perl的perlre文檔中學到了這個技巧,它在(?>...)的文檔中提到它。)

除了具有正確的語義之外,它還具有適當的性能屬性。 如果我們從perlre移植一個例子:

[nelhage@anarchique:~/tmp]$ cat re.py
import re
import timeit


re_1 = re.compile(r'''\(
                           (
                             [^()]+           # x+
                           |
                             \( [^()]* \)
                           )+
                       \)
                   ''', re.X)
re_2 = re.compile(r'''\(
                           (
                             (?=(?P<tmp>[^()]+ ))(?P=tmp) # Emulate (?> x+)
                           |
                             \( [^()]* \)
                           )+
                       \)''', re.X)

print timeit.timeit("re_1.search('((()' + 'a' * 25)",
                    setup  = "from __main__ import re_1",
                    number = 10)

print timeit.timeit("re_2.search('((()' + 'a' * 25)",
                    setup  = "from __main__ import re_2",
                    number = 10)

我們看到了顯着的改善:

[nelhage@anarchique:~/tmp]$ python re.py
96.0800571442
7.41481781006e-05

隨着我們擴展搜索字符串的長度,這只會變得更加引人注目。

根據這張表 ,答案是否定的。 創建了一個RFE以將其添加到Python 3中,但拒絕支持新的regex模塊,后者支持它:

>>> import regex
>>> regex.match('"(?>.*)"', '"Quote"')
>>> regex.match('"(.*)"', '"Quote"')
<_regex.Match object at 0x00C6F058>

注意: regex也適用於Python 2。

截至 2022 年 3 月 21 日,在創建此線程大約 10 年后,Python 終於在 Python 3.11.0a7: 提交鏈接中的標准庫re模塊中添加了原子分組(和所有格匹配)。 所以現在,該線程的所有答案都可能已過時; 以前,只有第三regex模塊具有原子分組和所有格匹配。 現在,它已經內置於 Python 的re模塊中。

這似乎不是。

http://www.regular-expressions.info/atomic.html

大多數現代正則表達式支持原子分組,包括JGsoft風格,Java,PCRE,.NET,Perl和Ruby。

您可以通過使用非捕獲組(?:RE)來模擬它們的非捕獲性,但如果我正確讀取它,那仍然不會給您帶來優化優勢。

來自http://docs.python.org/2/library/re.html#regular-expression-syntax

(ΔP<名稱> ...)

與常規括號類似,但是通過符號組名稱名稱可以在正則表達式的其余部分中訪問由組匹配的子字符串。 組名必須是有效的Python標識符,並且每個組名只能在正則表達式中定義一次。 符號組也是編號組,就像組未命名一樣。 因此,下面示例中名為id的組也可以作為編號組1引用。

例如,如果模式是(?P [a-zA-Z _] \\ w *),則可以通過匹配對象方法的參數在名稱中引用該組,例如m.group('id')或m .end('id'),以及正則表達式本身的名稱(使用(?P = id))和賦予.sub()的替換文本(使用\\ g)。

(ΔP=名)

Matches whatever text was matched by the earlier group named name.

暫無
暫無

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

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