Python基礎編【第3編】:Python正規表現

20511 ワード

正規表現
正規表現は特殊な文字シーケンスであり、文字列がパターンに一致しているかどうかを簡単にチェックすることができます.
Pythonは1.5バージョンからreモジュールを追加し、Perlスタイルの正規表現モードを提供しています.
reモジュールはPython言語にすべての正規表現機能を持たせる.
compile関数は、モード文字列とオプションのフラグパラメータに基づいて正規表現オブジェクトを生成します.このオブジェクトには、正規表現の一致と置換のための一連の方法があります.
reモジュールはまた、これらの方法の機能と完全に一致する関数を提供し、これらの関数は、モード文字列を最初のパラメータとして使用します.
この章では、Pythonでよく使われる正規表現処理関数について説明します.
文字:
  . 改行文字以外の任意の文字を一致させるwアルファベットまたは数字または下線または漢字を一致させるs任意の空白文字を一致させるd数字を一致させるb単語の開始または終了を一致させる^文字列の開始$文字列の終了を一致させる
回数:
*0回以上+1回以上繰り返しますか?0回以上{n}をn回{n,}をn回以上{n,m}をn回からm回繰り返す
正規表現は文字列に一致する強力な武器です.その設計思想は記述的な言語で文字列に規則を定義することであり、規則に合致する文字列であれば、私たちはそれが「一致」していると考えている.そうしないと、この文字列は合法的ではない.
たとえば、文字列が正当なEmailであるかどうかを判断する方法は、次のとおりです.
  • Emailに一致する正規表現を作成する.
  • この正規表現でユーザの入力にマッチして正当か否かを判断する.

  • re.match
    re.matchは文字列の開始位置からパターンをマッチングし、マッチングに成功した場合はMatchオブジェクトを返し、開始位置マッチングに成功しなければmatch()はnoneを返します.
    関数構文:
    re.match(pattern, string, flags=0)

    パラメータの説明
    パラメータ
    説明
    pattern
    一致する正規表現
    string
    一致する文字列.
    flags
    大文字と小文字を区別するかどうか、複数行のマッチングなど、正規表現のマッチング方法を制御するフラグビット.
    group(num)またはgroups()マッチングオブジェクト関数を使用してマッチング式を取得できます.
    オブジェクトの照合方法
    説明
    group(num=0)
    一致する式全体の文字列、group()は一度に複数のグループ番号を入力できます.この場合、それらのグループに対応する値を含むメタグループが返されます.
    groups()
    すべてのグループ文字列を含むメタグループを返します.1から含まれるグループ番号までです.
    # flags
    I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case
    L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale
    U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale
    M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline
    S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline
    X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments

    例1
    #!/usr/bin/python # -*- coding: UTF-8 -*- 
    
    import re print(re.match('www', 'www.runoob.com').span())  #         span                   
    print(re.match('com', 'www.runoob.com'))          #         

    結果:
    (0, 3)
    (11, 14)

    re.searchメソッド
    re.searchは文字列全体をスキャンし、最初の正常な一致を返します.一致成功re.searchメソッドは、一致するオブジェクトを返します.そうでなければNoneを返します.
    関数構文:
    re.search(pattern, string, flags=0)

    関数パラメータの説明:
    パラメータ
    説明
    pattern
    一致する正規表現
    string
    一致する文字列.
    flags
    大文字と小文字を区別するかどうか、複数行のマッチングなど、正規表現のマッチング方法を制御するフラグビット.
    group(num)またはgroups()マッチングオブジェクト関数を使用してマッチング式を取得できます.
    オブジェクトの照合方法
    説明
    group(num=0)
    一致する式全体の文字列、group()は一度に複数のグループ番号を入力できます.この場合、それらのグループに対応する値を含むメタグループが返されます.
    groups()
    すべてのグループ文字列を含むメタグループを返します.1から含まれるグループ番号までです.
    例:
    #!/usr/bin/python
    # -*- coding: UTF-8 -*- 
    
    import re
    print(re.search('www', 'www.runoob.com').span())      #        
    print(re.search('com', 'www.runoob.com').span())         #         

    結果:
    (0, 3)
    (11, 14)

    例2
    #!/usr/bin/python
    import re
    
    line = "Cats are smarter than dogs"; searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) if searchObj: print "searchObj.group() : ", searchObj.group() print "searchObj.group(1) : ", searchObj.group(1) print "searchObj.group(2) : ", searchObj.group(2) else: print "Nothing found!!"

    結果:
    searchObj.group() :  Cats are smarter than dogs
    searchObj.group(1) : Cats searchObj.group(2) : smarter

    re.matchとre.searchの違い
    re.matchは文字列の開始のみを一致させ、文字列の開始が正規表現に合致しない場合、一致に失敗し、関数はNoneを返す.そしてre.searchは、一致が見つかるまで文字列全体に一致します.
    例:
    #!/usr/bin/python
    import re
    
    line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I) if matchObj: print "match --> matchObj.group() : ", matchObj.group() else: print "No match!!" matchObj = re.search( r'dogs', line, re.M|re.I) if matchObj: print "search --> matchObj.group() : ", matchObj.group() else: print "No match!!"

    結果:
    No match!!
    search --> matchObj.group() :  dogs

    findall(pattern, string, flags=0)
    上記の2つの方法は、単一の値を一致させるために使用されます.すなわち、文字列の1つしか一致しません.文字列内のすべての条件を満たす要素に一致させるにはfindallを使用する必要があります.
    import re
    
    obj = re.findall('\d+', 'fa123uu888asf')
    print obj

    エスケープ文字(r)
    Pythonの文字列自体も\エスケープされているので注意:
    s = 'ABC\\-001' # Python     # # 'ABC\-001'

    そこでPythonのr接頭辞を強くお勧めします.エスケープの問題を考慮する必要はありません.
    s = r'ABC\-001' # Python     # # 'ABC\-001'

    正規表現が一致するかどうかを判断する方法を見てみましょう.
    >>> import re >>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345') <_sre.SRE_Match object; span=(0, 9), match='010-12345'>    #               。 >>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')

    グループ化
    正規表現には、マッチングの有無を簡単に判断するほか、サブストリングを抽出する強力な機能もあります.()で示すのが抽出するグループ(Group)である.例:^(\d{3})-(\d{3,8})$2つのグループをそれぞれ定義し、一致する文字列から直接区番とローカル番号を抽出することができる.
    >>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345') >>> m <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
    >>> m.group(0) '010-12345'
    >>> m.group(1) '010'
    >>> m.group(2) '12345'

    正規表現でグループが定義されている場合は、Matchオブジェクト上でgroup()メソッドでサブストリングを抽出できます.
    注意group(0)永遠にオリジナル文字列、group(1)group(2)・・第1、2、・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・サブストリングを抽出するのに役立ちます.
    もっと凶暴な例を見てみましょう
    >>> t = '19:05:30'
    >>> m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t) >>> m.groups() ('19', '05', '30')

    この正規表現は合法的な時間を直接識別することができる.しかし、識別日など、正規表現では完全な検証ができない場合があります.
    '^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'
    '2-30''4-31'という不正な日付については、正則ではまだ認識できない、あるいは書くのが非常に困難な場合は、プログラムを組み合わせて認識する必要があります.
    sub置換
    Pythonのreモジュールはreを提供した.subは、文字列内の一致するアイテムを置換するために使用されます.str.replaceよりも強力
    構文:
    re.sub(pattern, repl, string, count=0, flags=0)

    patternマッチングモード、replマッチング、stringマッチング文字列、countマッチング回数
    >>> re.sub('[abc]', 'o', 'Mark')
    >>> 'Mork'

    返される文字列は、REの一番左の重複しない一致で文字列に置き換えられます.パターンが見つからない場合、文字は変更されずに返されます.
    オプションパラメータcountは、モードマッチング後に置換される最大回数です.countは非負の整数でなければなりません.デフォルト値が0の場合、すべての一致が置き換えられます.
    例:
    #!/usr/bin/python
    import re phone = "2004-959-559 # This is Phone Number"
    
    # Delete Python-style comments
    num = re.sub(r'#.*$', "", phone) print "Phone Num : ", num # Remove anything other than digits
    num = re.sub(r'\D', "", phone) print "Phone Num : ", num

    結果
    Phone Num :  2004-959-559 Phone Num : 2004959559

    正規表現修飾子-オプションフラグ
    正規表現には、一致するモードを制御するオプションのフラグ修飾子が含まれます.修飾子はオプションのフラグとして指定されます.複数のフラグは、ビットOR(|)で指定できます.如re.I | re.MはIおよびMフラグに設定される.
    修飾子
    説明
    re.I
    照合を大文字と小文字に敏感にしない
    re.L
    ローカライズ識別(locale-aware)マッチングを行う
    re.M
    複数行一致、影響^および$
    re.S
    使改行を含むすべての文字を一致させる
    re.U
    Unicode文字セットに基づいて文字を解析します.このマークの影響w,W,b,B.
    re.X
    このフラグは、正規表現をより理解しやすく書くために、より柔軟なフォーマットを与えることができます.
    コンパイル
    Pythonで正規表現を使用すると、reモジュールの内部で2つのことができます.
  • 正規表現をコンパイルし、正規表現の文字列自体が合法でない場合、エラーを報告する.
  • コンパイルされた正規表現で文字列を一致させる.

  • 正規表現を何千回も繰り返し使用する場合は、効率的に正規表現を事前にコンパイルできます.次に繰り返し使用する場合は、このステップをコンパイルする必要はありません.直接一致します.
    >>> import re #   :
    >>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$') #
    >>> re_telephone.match('010-12345').groups() ('010', '12345') >>> re_telephone.match('010-8086').groups() ('010', '8086')

    コンパイル後にRegular Expressionオブジェクトが生成されます.このオブジェクト自体に正規表現が含まれているため、対応するメソッドを呼び出すときに正規文字列を与える必要はありません.
    split(pattern, string, maxsplit=0, flags=0)
    指定した一致に基づいてグループ化し、正規表現で文字列を分離します.正規表現をカッコで囲むと、一致する文字列もlistに含めて返されます.maxsplitは分離の回数で、maxsplit=1は1回分離され、デフォルトは0で、回数は制限されません.
    >>> re.split('\W+', 'Words, words, words.', 1) 
    ['Words', 'words, words.'] 
    content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
    new_content = re.split('\*', content)
    # new_content = re.split('\*', content, 1)
    print new_content
    content
    = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'" new_content = re.split('[\+\-\*\/]+', content) # new_content = re.split('\*', content, 1) print new_content
    inpp
    = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' inpp = re.sub('\s*','',inpp) new_content = re.split('\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)', inpp, 1) print new_content

    str.splitよりも強化されています
    コンピュータソース
    いくつかの例:
    IP:
    ^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
       :
    ^1[3|4|5|8][0-9]\d{8}$