正規表現

アサーション② (?= ) 先読み _key-visual

指定文字と1つ前の間で ...

 今回から、いよいよ先読みに入ります。

この先読みや、後読みなどは、その分かり難さから大変煙たがられています。

しかし、これらは今まで説明してきたアサーションの仲間です。

 アサーションとして、前々回 \b を説明しました。

この \b のマッチ箇所の一つに、\w と \W との間がありました。

\w というように、予め指定パターンが固定されていましたが、先読みの場合これを任意に設定できます。

 記述方法は (?= ) として、= の隣に任意のパターンを指定します。

このようにする事で、指定した文字とその前にある文字との間にマッチします。

 例えば、(?=円) ならば 円 とその前にある文字の間にマッチが生じます。

対象文字列が5円 5元の場合 対象文字列が5円 5元の場合のフローチャート\w


 このように位置にマッチする、というイメージの延長線上で捉えていくと、理解が容易になってきます。

基本的な動作原理は単純なのです。

 また、慣れる事で先読みに関する抵抗感が減らせるので、例をシンプルに、且つ最小構成で挙げて解説します。

難所と言われる先読みを制覇して、意のままに操りましょう。


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

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

 事前知識として、pythonから正規表現を扱う方法が必要になります。
また、正規表現における文字クラスの知識や、選択を表す正規表現である | OR(または) を理解している事が望ましいです。
(不安な人でも、【Pythonから使う】【基礎1 文字クラス】 【| OR(または)】、で詳しい解説があるので安心です。)
 シンプルな例を一個ずつ確認する事で、先読みに慣れていきましょう。

難度       :
事前知識: Pythonの基礎文法(reモジュールを含む)。正規表現の文字クラスや選択等。
学習効果:  先読みの性質である、任意に設定したパターンの前にマッチする、という事を理解出来る。

Contens  |   目次

Chapter1 Pythonで実行

Chapter1   Pythonで実行

(?=a)

 最初の例として、文字列パターンが (?=a) の場合を考えます。

これは、a とその前にある文字の間にマッチします。

対象文字列が map なら a とその前にある m の間です。

    re_meta20_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

 予想通り、ma の間にマッチしました。

a を先頭や末尾にも並べて、 aaa のようにして実行してみます。

各々 a の前にヒットするはずです。

    re_meta20_2.py

        import  re

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


実行結果 アサーション② (?= ) 先読み_2

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

次に空白を挟んで、a a を対象文字列とします。

    re_meta20_3.py

        import  re

        # a と a の間は半角スペース
        pattern = re.compile("(?=a)")
        st = "a a"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 アサーション② (?= ) 先読み_3

 スペースが存在しても、a の前にマッチするという性質は変わりません。

もう一つ例を挙げます。

文字列パターンが (?=s) であり、対象文字列を seasons とする場合です。

    re_meta20_4.py

        import  re

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


実行結果 アサーション② (?= ) 先読み_4

 それぞれ s の前にマッチしています。

今度は、(?=s) だけでなく単語と組み合わせて使ってみます。

a(?=s)

 対象文字列は、meta20_4.py と同様に seasons とします。

但し、文字列パターンを a(?=s) とする事で、s の前にある a という文字にマッチします。

    re_meta20_5.py

        import  re

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


実行結果 アサーション② (?= ) 先読み_5

 狙い通り、a という文字に一致しました。

次の例では、通貨表示が である数字を取得します。

    re_meta20_6.py

        import  re

        pattern = re.compile("\d(?=円)")
        st = "5円 3元 9ドル 1円 8貫文 €7"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 アサーション② (?= ) 先読み_6

 5円を取得出来ました。

メタキャラクタと組み合わせて、の他にドルの値もその対象にします。

(?= | )

 選択(OR)を表す正規表現は | です。

(| については【| OR(または)】で詳しく説明しています。)

\d(?=円|ドル) のようにすると、円の他にドルの前にある数字にマッチします。

    re_meta20_7.py

        import  re

        pattern = re.compile("\d(?=円|ドル)")
        st = "5円 3元 9ドル 8貫文 €7"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 アサーション② (?= ) 先読み_7

 5円の他に9ドルを得られました。

この他にも、$ を使ってみます。

$ は、文字列の末尾を意味します。

($ については【$ 文字列の末尾】で詳しく説明しています。)

 文末の日付を抽出するには、以下のようにします。

    re_meta20_8.py

        import  re

        pattern = re.compile("\d(?=日$)")
        st = "令和2年3月4日 平成4年8月9日"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


実行結果 アサーション② (?= ) 先読み_8

 4日ではなく、9日を対象にできました。

続けて例を出します。

. の前にある数字を狙います。

. はそのまま使うと任意の1文字になってしまうので、\ (バックスラッシュ)と併用します。

(\ については【\ エスケープ文字の働き】で詳しく説明しています。)

    re_meta20_9.py

        import  re

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


実行結果 アサーション② (?= ) 先読み_9

 問題無く取得出来ました。



 先読みの説明はここで終了です。

多くの例をみてきたので、先読みの性質である、任意に設定したパターンの前にマッチする、という事を理解出来ました。

これにより、取得したい部分が、ある文字列の前にある場合に役立つでしょう。

 次回は、先読みとは反対の位置にマッチする後読みです。

関連記事

基礎4 アサーション② /b _key-visual

\b 単語の境界

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラス等。
学習効果: 単語の境界とされる位置を的確に認識できるようになる。
基礎4 アサーション② /B _key-visual

\B 単語の境界でない

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラス等。
学習効果: 単語の境界でない位置を的確に認識できるようになる。
基礎4 アサーション② (?= ) _key-visual

(?= ) 先読み

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラスや選択等。
学習効果: 先読みの性質である、任意に設定したパターンの前にマッチする、という事を理解出来る。
基礎4 アサーション② (?<= ) _key-visual

(?<= ) 後読み

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラスや選択等。
学習効果: 後読みの性質である、任意に設定したパターンの後にマッチする、という事を理解出来る。
基礎4 アサーション② (?! ) _key-visual

(?! ) 否定先読み

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラスや選択等。
学習効果: 否定先読みの性質である、任意に設定したパターン以外の前でマッチする、という事を理解出来る。
基礎4 アサーション② (?<! ) _key-visual

(?<! ) 否定後読み

正規表現: アサーション②
難度       : 基礎
事前知識: Python基礎(reモジュール)。文字クラスや選択等。
学習効果: 否定後読みの性質である、任意に設定したパターン以外の後でマッチする、という事を理解出来る。
Pythonで正規表現を使う1

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

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

ハロー ! メタキャラクタ

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

正規表現とは?

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

PR