36

Ruby の正規表現には、ここ(?>regexp)で説明されているアトミック グループ化と呼ばれる機能があります。Python のモジュールに同等のものはありますか?re

4

4 に答える 4

50

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

検索文字列の長さを拡張すると、これはさらに劇的になります。

于 2012-11-27T04:29:24.940 に答える
16

この表によると、答えはノーです。それを Python 3 に追加するためにRFEが作成されましたが、それをサポートする新しいregexモジュールを支持して拒否されました。

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

注: regexPython 2 でも使用できます。

于 2012-11-27T04:31:56.007 に答える
0

そうではないようです。

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

アトミック グループ化は、JGsoft フレーバー、Java、PCRE、.NET、Perl、Ruby など、最新の正規表現のほとんどでサポートされています。

非キャプチャ グループを使用して、それらの非キャプチャ性をエミュレートできますが、(?:RE)正しく読んでいれば、それでも最適化のメリットは得られません。

于 2012-11-27T04:35:46.857 に答える
-3

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.
于 2012-11-27T04:26:54.530 に答える