正規表現

量指定子 * _key-visual

0回でもOK!

 それでは、ここから正規表現の中で、文字列パターンの繰り返しを表現する量指定子をみていきます。

この量指定子は、パターンの一部が何度も繰り返される場合に、その威力を発揮します。

 例えば、対象文字列が bee だとします。

この場合、マッチさせる最も単純なパターンとして bee と表現出来ます。

見ての通り eee を二回分記述しています。

ここで量指定子を用いると、繰り返しを表現できるので一回分の記述で済みます。

 今回は、量指定子の中でも * を使います。

* は、直前の正規表現を 0 回以上、できるだけ多く繰り返す事を意味します。

上の例であるならば、 e* のようにすると、e の繰り返しを表せます。

故に、be* のようにパターンを構成できます。

 また * は、直前の正規表現を 0 回以上、としています。

したがって、e* ならば e が0回、つまり対象とする文字列が b の場合にもマッチします。

パターンが be* の場合 パターンが be* の場合のフローチャート\w


 今回もシンプルな例を試しながら、徐々に慣れていきましょう。


この記事の難度は、基礎  Cクラスです。

(A: やさしい   →   E: 難しい)

 事前知識として、pythonから正規表現を扱う方法が必要になります。
また、正規表現における文字クラスの知識や、グループを表す正規表現である ( ) を理解している事が望ましいです。
(不安な人でも、【Pythonから使う】【基礎1 文字クラス】 【( ) グループを指定】【( ) キャプチャを使う】、で詳しい解説があるので安心です。)
 先ずは簡単な例で、繰り返しを表現する量指定子に慣れていきます。
* の動作を確認しましょう。

難度       :
事前知識: Pythonの基礎文法(reモジュールを含む)。正規表現の文字クラスやグループ等。
学習効果:   * が直前の正規表現を 0 回以上、できるだけ多く繰り返す事を理解できる。

Contens  |   目次

Chapter1 Pythonで実行

Chapter1   Pythonで実行

a*

 先ず文字列パターンを、アルファベット1文字の a* を組み合わせて a* とします。

これは a の0回以上の繰り返しを表します。

a はあっても無くてもよいので、対象文字列が map なら、1回出現している a の他にもマッチするはずです。

    re_meta24_1.py

        import  re

        pattern = re.compile("a*")
        st = "map"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_1

 予想通り、a 以外にもマッチしました。

次にパターンを ma*p にします。

mp の間の a が繰り返すか、あるいは無い場合に一致するはずです。

    re_meta24_2.py

        import  re

        pattern = re.compile("ma*p")
        st = "mp map maap"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_2

 これも想定通りの結果です。

a が存在しない mp や、繰り返している map , maap などと一致しました。

これに対して、対象文字列を mop としてしまうと、a の代わりに o が存在するのでマッチしません。

    re_meta24_3.py

        import  re

        pattern = re.compile("ma*p")
        st = "mop"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_3

 mop ではマッチしない事が確認出来ました。

さて、ここで冒頭で例示した bee について実行してみましょう。

パターンを be* と構成する事で、e のできるだけ多くの繰り返しにマッチします。

よって、対象文字列が beeeeeee のように、e が多く繰り返されていてる場合でもヒットします。

    re_meta24_4.py

        import  re

        pattern = re.compile("be*")
        st = "bee b beeeeeee"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_4

 bee だけでなく、bbeeeeeee にもヒットしています。

(es)*

 今度は、グループ化されたものを繰り返しの対象とします。

グループを表す正規表現は ( ) です。

(グループ については【( ) グループを指定】で詳しく説明しています。)

パターンを (es) の繰り返しにする場合、(es)* のように記述します。

    re_meta24_5.py

        import  re

        pattern = re.compile("gen(es)*")
        st = "gen genes geneses"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_5

 それぞれ、es の0回の繰り返しである gen あるいは、1回、2回である genes , geneses に一致しました。

さらに、次の例では (es)後方参照を試しています。

(後方参照 については【( ) キャプチャを使う】で詳しく説明しています。)

 パターンは、シンプルに (es)*\1 にしましょう。

対象文字列は、先程と同様なものに geneseseses 加えた gen genes geneses geneseseses です。

    re_meta24_6.py

        import  re

        pattern = re.compile(r"gen(es)*\1")
        st = "gen genes geneses geneseseses"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("----- match -----")
            for  i   in  range(result.lastindex + 1):
              print('group{num};'.format(num = i),result.group(i))
              print("位置",result.span(i))
                            


実行結果 量指定子 *_6

実行結果(続き) 量指定子 *_6

 geneses , geneseseses にはマッチしましたが、gen , genes にはマッチしていません。

グループに量指定子を組み合わせてから、後方参照を (es)*\1 のように行っても、あくまで es と、その参照が必要になる事は変わらないようです。

((es)*)

 次の例では、(es)* 自体を ( ) で括ってグループ化してみましょう。

パターン以外は、一つ前に実行した meta24_6.py と同様にして、結果の違いに注意しながら試します。

    re_meta24_7.py

        import  re

        pattern = re.compile(r"gen((es)*)\1")
        st = "gen genes geneses geneseseses"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("----- match -----")
            for  i   in  range(result.lastindex + 1):
              print('group{num};'.format(num = i),result.group(i))
              print("位置",result.span(i))
                            


実行結果 量指定子 *_7_1

実行結果(続き) 量指定子 *_7_2

実行結果(続き2) 量指定子 *_6

 meta24_6.py のときとは異なり、対象文字列の全てに一致しました。

各々、0回、1回、2回分に該当する後方参照が行われたようです。

\d*

 続けて例を出します。

数字を表す文字クラスである \d* を組み合わせて、数字の繰り返しを狙います。

(文字クラス については【\d 数字を指定する】で詳しく説明します。)

    re_meta24_8.py

        import  re

        pattern = re.compile("¥\d*")
        st = "¥ ¥7 ¥77 ¥777"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 量指定子 *_8

実行結果(続き) 量指定子 *_6

 0回の分も含めて ¥ 表示の金額を取得出来ました。



 以上で * の解説は終わりにします。

平易な例を通じて、*直前の正規表現を 0 回以上、できるだけ多く繰り返す事を理解できました。

量指定子は * 以外にもあるので、次回+ を学習しましょう。

関連記事

基礎5 量指定子 * _key-visual

* 繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: * が直前の正規表現を 0 回以上、できるだけ多く繰り返す事を理解できる。
基礎5 量指定子 + _key-visual

+ 繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: + が直前の正規表現を 1 回以上、できるだけ多く繰り返す事を理解できる。
基礎5 量指定子 ? _key-visual

? 繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: ? が、直前の正規表現を0回か、1回繰り返したものにマッチさせる事を理解できる。
基礎5 量指定子 { } _key-visual

{ } 繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: { } が、直前の正規表現を指定した回数、ちょうど繰り返したものにマッチさせる事を理解できる。
基礎5 量指定子 { } _key-visual

{ , } 繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: {m,n} が、直前の正規表現を m 回から n 回、できるだけ多くの繰り返しにマッチする事が分かる。
基礎5 量指定子 { } _key-visual

*?   +?   ??   { , }?   繰り返し

正規表現: 量指定子
難度       : 基礎
事前知識: Pythonの基礎。文字クラスやグループ等。
学習効果: *?   +?   ??   { , }?   が、非貪欲 (non-greedy)のマッチになる事を理解できる。
Pythonで正規表現を使う1

正規表現をPythonから使うには ?

正規表現: Pythonから使う
難度       : 入門
事前知識: Pythonの基礎文法
学習効果: pythonから正規表現を使う一連の流れを掴む
メタキャラクタに馴染む_key-visual

ハロー ! メタキャラクタ

正規表現: メタキャラクタの概要
難度       : 入門
事前知識: 不要
学習効果: メタキャラクタの概要を掴む
正規表現の概要_key-visual

正規表現とは?

正規表現: 概要
難度       : 入門
事前知識: 不要
学習効果: 正規表現の概要を知る
正規表現の概要

PR