2017-04-04 12 views
1

が先行または後続しない桁の具体的な数は、私は、文字列があります。マッチ桁

string = u'11a2ee22b333c44d5e66e777e8888' 

を私はn <= k <= m桁の全てk連続したチャンクを見つけたいです。唯一の正規表現を使用して

: は例n=2m=3 のために言う(?:\D|^)(\d{2,3})(?:\D|$)

re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888') 

を使用して、この出力を提供します:

['11', '333', '66'] 

所望の出力:

['11', '22', '333', '44', '66', '777'] 

代替ソリューションがあります:

filter(lambda x: re.match('^\d{2,3}$', x), re.split(u'\D',r'11a2ee22b333c44d5e66e777e8888')) 

希望の出力が得られますが、最初のアプローチで何が問題なのかを知りたいのですか?

一致するとre.findallが順番に前の部分をスキップしているようですので、何ができますか?

+0

はhttps://regex101.com/であなたのパターンを試してみてください、または多くのオンラインのPythonの他には、正規表現テスターを風味。パターンの仕組みを示す説明やグラフィックを示すものもあります。 – wwii

+1

あなたのキャプチャしていない*グループ*はテキストを消費します。 '' re.findall'''は、重複しないマッチだけを返します。あなたがテキストを消費すると、オーバーラップを作成することになります。試してください*アサーションを見て*、*ネガティブな先読みアサーション*、正と負の*見た目のアサーション*。 – wwii

答えて

2

注:あなたは、あなたの質問に表示結果は私が取得していますものではありません。

>>> import re 
>>> re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888') 
[u'11', u'22', u'44', u'66'] 

それはまだあなたが欲しい試合の一部が欠けていますが、ではないのと同じもの。

問題が(?:\D|^)(?:\D|$)のようにもかかわらず、非キャプチャグループは、彼らが一致したものではないキャプチャを行うことで、彼らはまだそれを消費します。 (\d{2,3})で撮影した(それでも消費)ではない

  • 22 - -

    1. eを、(?:\D|^)(?:\D|$)
    2. bを捕獲 - ない:

      これは'22'を生み出すマッチが実際に消費したことを意味捕獲された(しかしそれでも消費される)

    ... 333の前にbを照合することはできません。

    あなたが後読みと先読み構文であなたが望む結果を得ることができます。

    ここ
    >>> re.findall(u'(?<!\d)\d{2,3}(?!\d)',u'11a2ee22b333c44d5e66e777e8888') 
    [u'11', u'22', u'333', u'44', u'66', u'777'] 
    

    (?<!\d)は、負の後読みで一致が数字が付いていないことを確認し、(?!\d)は否定先読みで、一致した後に数字がないことを確認する。重大なことに、これらの構成は文字列のいずれも消費しません。

    さまざまなルックアヘッドおよびルックビハインドの構造については、Pythonのreドキュメントの Regular Expression Syntaxセクションに記載されています。

  • 1

    \ d {2,3}は2桁または3桁を意味し、(?= [a-z])は数字の後の文字を意味します。

    In [136]: re.findall(r'(\d{2,3})(?=[a-z])',string) 
    Out[136]: ['11', '22', '333', '44', '66', '777'] 
    
    1

    あなたも、機能とそれを一般化できます。

    import re 
    
    string = "11a2ee22b333c44d5e66e777e8888" 
    
    def numbers(n,m): 
        rx = re.compile(r'(?<!\d)(\d{' + '{},{}'.format(n,m) + '})(?!\d)') 
        return rx.findall(string) 
    
    print(numbers(2,3)) 
    # ['11', '22', '333', '44', '66', '777']