[英]Do Python regular expressions have an equivalent to Ruby's atomic grouping?
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
隨着我們擴展搜索字符串的長度,這只會變得更加引人注目。
這似乎不是。
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.