Python: 正規表現の基本 – 最長、最短マッチング

直前の文字、メタ文字を繰り返しマッチングさせる量指定記号である「*」「+」「?」などは、テキスト中にその繰り返しパターンがマッチする箇所が複数ある場合は、通常最後にマッチした箇所をオブジェクトに記録します。このような最長マッチングに対して、マッチング箇所が複数の場合に最初にマッチした箇所を記録する最短マッチング方法があります。
最短マッチングを行う量指定記号は最長マッチングの記号の末尾に「?」を付けるだけです。すなわち、最長の量指定が「*」「+」「?」であるのに対して、最短マッチングは「*?」「+?」「??」となります。それでは、以下のコードで確認してみましょう。

ソースコード

# coding: Shift_JIS
import re # 正規表現を扱うモジュールのインポート
# 正規表現のチェックプリント用の関数
def PrintRegMatch(pat, txt):
    #   書式: re.search(パターン, テキスト)
    m = re.search(pat, txt) # パターンにマッチしなかった場合はNoneを返す
    if m != None:
        print 'パターン: "%s"nテキスト: "%s"nマッチ  : する' % (pat, txt)
        print 'マッチング開始位置:', m.start()
        print 'マッチング終了位置:', m.end()
    else:
        print 'パターン: "%s"nテキスト: "%s"nマッチ: しない' % (pat, txt)
    print
    return m
# サンプルテキスト
txt = '<p>Hello! World!!</p><p>Goodbye World</p>'
# 最長: .*
# 最短: .*?
PrintRegMatch('<p>.*</p>',  txt) # 最長: 文字列末尾の</p>にマッチ
PrintRegMatch('<p>.*?</p>', txt) # 最短: World!!</p>の</p>にマッチ
# 最長: .+
# 最短: .+?
PrintRegMatch('<p>.+</p>',  txt) # +?は直前の文字の1文字以上の繰り返し
PrintRegMatch('<p>.+?</p>', txt) # ↑の控えめマッチング
# 最長: .?
# 最短: .??
PrintRegMatch('B.?C',  'BCCC')   # ?は直前の文字の0 or 1回の繰り返し
PrintRegMatch('B.??C', 'BCCC')   # ??はその控えめ(ry

re.searchはre.matchと異なり、パターンをテキスト文字列の先頭以外にもマッチさせます。

実行結果

パターン: "<p>.*</p>"
テキスト: "<p>Hello! World!!</p><p>Goodbye World</p>"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 41
パターン: "<p>.*?</p>"
テキスト: "<p>Hello! World!!</p><p>Goodbye World</p>"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 21
パターン: "<p>.+</p>"
テキスト: "<p>Hello! World!!</p><p>Goodbye World</p>"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 41
パターン: "<p>.+?</p>"
テキスト: "<p>Hello! World!!</p><p>Goodbye World</p>"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 21
パターン: "B.?C"
テキスト: "BCCC"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 3
パターン: "B.??C"
テキスト: "BCCC"
マッチ  : する
マッチング開始位置: 0
マッチング終了位置: 2

リファレンス

コメント

  1. 愛宕翔太 より:

    ここにpython使った正規表現使ったサンプル落ちてる
    @yukun_ I just read

  2. […] Python: 正規表現の基本 – 最長、最短マッチング -> 繰り返しパターンがマッチするケースでどのように実装するかが参考になりました。 […]