正規表現

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

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

 前々回で先読みを説明しました。

これらは、指定した文字の前にマッチする正規表現でした。

 今回紹介する否定先読みは、それとは逆の性質をもち、指定したパターン以外の前でマッチを発生させます。

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

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

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


 今回も平易な例を使い解説します。


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

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

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

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

Contens  |   目次

Chapter1 Pythonで実行

Chapter1   Pythonで実行

(?!a)

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

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

対象文字列が map なら m と 先頭あるいは、p とその前にある a や、末尾と p の間です。

    re_meta22_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 を先頭や末尾にも並べて、 aaa のようにして実行してみます。

末尾と a の間のみヒットするはずです。

    re_meta22_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_meta22_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_meta22_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) だけでなく単語と組み合わせて使ってみます。

t(?!s)

 対象文字列は、registrants とします。

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

    re_meta22_5.py

        import  re

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


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

 狙い通りの t に一致しました。

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

    re_meta22_6.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())        
                            


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

 通貨表示が 以外の金額を取得出来ました。

しかし、ここでは €7 も対象になっています。

金額の後に通貨表示がある書式だけを、その対象にするには \B を併用しましょう。

(\B については【\B 単語の境界でない】で詳しく説明しています。)

    re_meta22_7.py

        import  re

        pattern = re.compile("\d(?!元)\B")
        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

 €7 は除外できました。

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

(?= | )

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

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

\d(?!元|ドル) のようにすると、ドル でない金額にマッチします。

    re_meta22_8.py

        import  re

        pattern = re.compile("\d(?!元|ドル)\B")
        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())        
                            


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

 5円と8貫文のみ得られました。

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

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

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

 末尾以外の金額を抽出するには、以下のようにします。

    re_meta22_9.py

        import  re

        pattern = re.compile("\d(?!円$)")
        st = "1円 2円 3円 5円"
        print("↓ 対象文字列\n"+st)
        result_iter = pattern.finditer(st)
        for  result   in  result_iter:
            print("match:",result.group())
            print("位置",result.span())        
                            


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

 5円以外を対象にできました。

続けて例を出します。

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

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

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

    re_meta22_10.py

        import  re

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


実行結果 アサーション② (?! )否定先読み_10

 . 以外の前にある数字のみを取得出来ました。



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

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

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

 次は、否定後読みに移ります。

関連記事

基礎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