Ответ 1
Python напрямую не поддерживает эту функцию, но вы можете эмулировать ее, используя утверждение lookahead с нулевой шириной ((?=RE)
), которое соответствует текущей точке с той же семантикой, которую вы хотите, поместив именованную группу ((?P<name>RE)
) внутри lookahead, а затем используя именованное backreference ((?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
:
[[email protected]:~/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)
Мы видим резкое улучшение:
[[email protected]:~/tmp]$ python re.py
96.0800571442
7.41481781006e-05
Что только становится более драматичным, поскольку мы расширяем длину строки поиска.