Pythonの正規表現はすべての重複する一致を見つけますか?


98

私はPython 2.6でreを使用して、10桁の一連の数字をより大きな一連の数字の中から見つけようとしています。

重複する一致を簡単に取得することはできませんが、数値シリーズのすべての一致が必要です。例えば。

「123456789123456789」内

次のリストを取得する必要があります。

[1234567891,2345678912,3456789123,4567891234,5678912345,6789123456,7891234567,8912345678,9123456789]

「先読み」への参照を見つけましたが、私が見た例では、大きなグループではなく数のペアしか表示されず、2桁を超えて変換することができませんでした。


6
提示されたソリューションは、重複する一致が同じポイントで始まる場合は機能しません。たとえば、「a | ab | abc」と「abcd」の一致は1つの結果のみを返します。「終了」境界を手動で追跡して、match()を複数回呼び出す必要がない解決策はありますか?
ビトー・デ・アラウージョ

@VítorDeAraújo:などの重複する正規表現(a|ab|abc)は、一般に、ネストされたキャプチャグループを使用して、重複しない正規表現に書き換えることができ(a(b(c)?)?)?ます。確かに、これは少し痛くて読みにくくなります。これは、一致するよりパフォーマンスの高い正規表現にもなります。
smci

回答:


175

先読み内でキャプチャグループを使用します。先読みは関心のあるテキストをキャプチャしますが、実際の一致は技術的には先読みの前のゼロ幅のサブストリングであるため、一致は技術的に重複しません。

import re 
s = "123456789123456789"
matches = re.finditer(r'(?=(\d{10}))',s)
results = [int(match.group(1)) for match in matches]
# results: 
# [1234567891,
#  2345678912,
#  3456789123,
#  4567891234,
#  5678912345,
#  6789123456,
#  7891234567,
#  8912345678,
#  9123456789]

2
私の答えはこれより少なくとも2倍速い。しかし、このソリューションはトリッキーです、私はそれを賛成します。
eyquem 2013

16
説明=パターン(10桁)を検索する代わりに、パターンに続くものを検索します。したがって、文字列の位置0、文字列の位置1などを検出します。次に、group(1)-一致するパターンを取得して、それらのリストを作成します。とてもかっこいい。
Tal Weiss

私は、先読みの中で一致グループを使用できるとは思いませんでした。これは通常、一致に含まれるべきではない(そして一致したサブグループは実際には完全一致には表示されません)。この手法はPython 3.4でも機能するようですが、これはバグではなく機能と考えられます。
JAB 2014年

10
私はStackOverflowに参加して質問に答え、この回答に賛成できるように評判を上げました。私は今のところPython 2.4にこだわっているので、Python 3のより高度な正規表現関数を使用できません。これは、私が探していた一種の奇妙なトリックです。
TheSoundDefense 14

2
コードに説明を追加してください。Stack Overflowのように、コードを回答に含めるのは最善の方法ではありません。それは間違いなく人々を助けるでしょう。
Akshay Hazari 2017

77

重複する一致をサポートするサードパーティのregexモジュール(ではないre)を使用することもできます

>>> import regex as re
>>> s = "123456789123456789"
>>> matches = re.findall(r'\d{10}', s, overlapped=True)
>>> for match in matches: print match
...
1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

17

私は正規表現が好きですが、ここでは必要ありません。

単に

s =  "123456789123456789"

n = 10
li = [ s[i:i+n] for i in xrange(len(s)-n+1) ]
print '\n'.join(li)

結果

1234567891
2345678912
3456789123
4567891234
5678912345
6789123456
7891234567
8912345678
9123456789

10
「より大きな一連の数値内」の特別な知識を適用しているため、ここでは正規表現は必要ありません。したがって、すべての位置0 <= i < len(s)-n+1が10桁の一致の開始であることが保証されています。また、あなたのコードがスピードアップする可能性があると私は考えます、スピードのためにコードゴルフに興味があるでしょう。
smci
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.