Ruby の正規表現には、ここ(?>regexp)
で説明されているアトミック グループ化と呼ばれる機能があります。Python のモジュールに同等のものはありますか?re
4 に答える
Python はこの機能を直接サポートしていませんが、ゼロ幅の先読みアサート ( (?=RE)
) を使用してエミュレートできます。これは、希望する同じセマンティクスで現在のポイントから一致し、名前付きグループ ( (?P<name>RE)
) を先読み内に配置してから、(?P=name)
ゼロ幅アサーションが一致したものと正確に一致する名前付き後方参照 ( )。一緒に組み合わせると、追加の一致するグループと多くの構文を作成するという犠牲を払って、同じセマンティクスが得られます。
たとえば、あなたが提供したリンクはRubyの例を示しています
/"(?>.*)"/.match('"Quote"') #=> nil
Python でそれをエミュレートできます。
re.search(r'"(?=(?P<tmp>.*))(?P=tmp)"', '"Quote"') # => None
内部グループが final を食べないように変更しても、"
まだ一致するため、ライン ノイズを吐き出すだけでなく、何か有用なことを行っていることを示すことができます。
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<名前>...)
通常の括弧に似ていますが、グループによって一致した部分文字列は、シンボリック グループ名 name を介して正規表現の残りの部分からアクセスできます。グループ名は有効な Python 識別子である必要があり、各グループ名は正規表現内で 1 回だけ定義する必要があります。シンボリック グループは、グループに名前が付けられていないかのように、番号付きのグループでもあります。したがって、以下の例の 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.