12

私の理解から、

(.)(?<!\1)

一致することはありません。実際、phppreg_replaceはこれをコンパイルすることさえ拒否しており、ruby も同様gsubです。ただし、 pythonreモジュールには別の意見があるようです。

import re
test = 'xAAAAAyBBBBz'
print (re.sub(r'(.)(?<!\1)', r'(\g<0>)', test))

結果:

(x)AAAA(A)(y)BBB(B)(z)

誰でもこの動作について合理的な説明を提供できますか?

アップデート

この動作は、モジュールの制限のようです。re代替regexモジュールは、アサーションのグループを正しく処理しているようです:

import regex

test = 'xAAAAAyBBBBz'

print (regex.sub(r'(.)(?<!\1)', r'(\g<0>)', test))
## xAAAAAyBBBBz

print (regex.sub(r'(.)(.)(?<!\1)', r'(\g<0>)', test))
## (xA)AAA(Ay)BBB(Bz)

とは異なりpcreregexでは可変幅の後読みも可能であることに注意してください。

print (regex.sub(r'(.)(?<![A-Z]+)', r'(\g<0>)', test))
## (x)AAAAA(y)BBBB(z)

PEP 411で言及されているように、最終的にregexは標準ライブラリに含まれる予定です。

4

1 に答える 1

6

reこれは、Pythonモジュールの制限 (Microsoft のサポート コールから学んだように、"バグ" の良い言い方です) のように見えます。

Python が可変長の後読みアサーションをサポートしていないという事実に関係していると思いますが、それ\1が常に固定長であることを理解するほど賢くはありません。正規表現をコンパイルするときにこれについて文句を言わない理由はわかりません。

面白いことに:

>>> print (re.sub(r'.(?<!\0)', r'(\g<0>)', test))
(x)(A)(A)(A)(A)(A)(y)(B)(B)(B)(B)(z)
>>>
>>> re.compile(r'(.*)(?<!\1)') # This should trigger an error but doesn't!
<_sre.SRE_Pattern object at 0x00000000026A89C0>

したがって、Python では後読みアサーションで後方参照を使用しない方がよいでしょう。肯定的な後読みはあまり良くありません (ここでも、肯定的な先読みであるかのように一致します)。

>>> print (re.sub(r'(.)(?<=\1)', r'(\g<0>)', test))
x(A)(A)(A)(A)Ay(B)(B)(B)Bz

そして、私はここで何が起こっているのか推測さえできません:

>>> print (re.sub(r'(.+)(?<=\1)', r'(\g<0>)', test))
x(AA)(A)(A)Ay(BB)(B)Bz
于 2012-04-23T11:17:53.487 に答える