クウネルマナブ

個人的なメモです(笑) 最近は、もっぱら趣味。WEBシステムを作るべくpython,HTML,PHPあたりの勉強を中心にしています!

正規表現

正規表現がいまいち飲み込めないので、確認用のメモ

 

使用環境

MacBookPro macOS Sierra10.12.4

python 3.6.0 

 

 

主なメタ文字とパターン

 .

任意の1文字をマッチ

例) a.c → aac abc acc などにマッチ

 

 [ ]

[ ]で囲まれた文字のいずれか1文字にマッチ

例) a[bc]d → abd acb にマッチ

 

 [ ] 内の-

- での範囲を表す

例) [0-9] → 0〜9の中のいずれか1文字にマッチ

 

 [ ]内の^

^ を最初につけることで否定を表す

例) [^abc] → a,b,c以外の任意の1文字にマッチ

 

 ^

行の先頭にマッチする

例) ^abc → 行頭にあるabcのみマッチ

 

 $

行の末尾にマッチ

例) xyz$ → 行末のxyzのみマッチ

 

 *

直前のパターンを0回以上繰り返す

例) ab*c → ac abc abbc abbbc などの文字列にマッチ

 

 +

直前のパターンを1回以上繰り返す

例) ab+c → abc abbc abbbc などの文字列にマッチ

 

 ?

直前のパターンを0回か1回繰り返す

例) ab?c → ac abc にマッチ

 

 {n}

直前のパターンをちょうどn回繰り返す

例) ab{3}c → abbbcにマッチ

 

 ( )

 ( )で囲まれたパターンをグループ化する

例) (ab)+ → ab abab ababab などの文字列にマッチ

 

 |

|で区切られたパターンのいずれかにマッチ

例) a(bc|cd|de)f → abcf acdf adef にマッチ 

 

 

主だったテクニックってとこでしょうか。。。

 

 

python3ににおける使用例

正規表現を使うには、標準モジュールの「re」を使用

※ import re

 

 re.seach()  re.findall()  re.sub()

以下公式ドキュメントより拝借

re.search(pattern, string, flags=0)

string を走査し、正規表現 pattern がマッチする最初の場所を探して、対応する match オブジェクト を返します。文字列内にパターンにマッチする場所が無い場合は None を返します; これは文字列内のある場所で長さが 0 のマッチが見つかった場合とは異なることに注意してください。

 

re.findall(pattern, string, flags=0)(原文)

patternstring へのマッチのうち、重複しない全てのマッチを文字列のリストとして返します。 string は左から右へと走査され、マッチは見つかった順番で返されます。パターン中に何らかのグループがある場合、グループのリストを返します。グループが複数定義されていた場合、タプルのリストになります。他のマッチの開始部分に接触しないかぎり、空のマッチも結果に含められます。

 

re.sub(pattern, repl, string, count=0, flags=0)(原文)

string 内で、pattern のマッチを repl で置き換えた文字列を返します。パターンが重複している場合は、一番左のマッチのみを置き換えます。パターンが見つからなければ string を変更せずに返します。repl は文字列でも関数でも構いません; 文字列の場合、バックスラッシュエスケープは処理されます。すなわち、\n は単一の改行文字に変換され、\r はキャリッジリターンに変換されます。\& のような未知のエスケープは処理されず、そのままにされます。\6 のような後方参照は、パターンのグループ 6 とマッチした部分文字列で置換されます。 

 

Python 3.6.1 ドキュメント

 

  

実際に使用してみる

正規表現のパターンには\(バックスラッシュ)が頻発するため、面倒なのでraw文字列「r'....'」(「r"......"」)という形式の文字列リテラルを使うと、バックスラッシュがエスケープ文字として解釈されないので、正規表現のパターンをスッキリできる。

 

対話モードにて実施。

マッチする場合 → Matchオブジェクト

 

re.search()関数で第2引数の文字列が第1引数の正規表現にマッチするか?

import re
re.search(r'a.*c','abc123DEF')
=> <_sre.SRE_Match object; span=(0, 3), match='abc'>

 Machtオブジェクトが得られ、macth='abc'でabcにマッチ

 

re.search()関数でマッチしない場合何も表示されない

import re
re.search(r'a.*d','abc123DEF')
=>

 

re.search()関数は第3引数の指定可能

import re
re.search(r'a.*d','abc123DEF',re.I)
=> <_sre.SRE_Match object; span=(0, 7), match='abc123D'>

re.I を指定すると大文字小文字の違いが無視されるため、マッチする。

その他、改行を含む全ての文字にマッチする「re.S」などもある

 

Matchオブジェクトのgroup()メソッドでマッチした値も取得できる

import re
m = re.search(r'a(.*)c','abc123DEF')
m.group(0)
=> 'abc'

引数に0を指定すると、正規表現全体にマッチした値が得られる。

 

group()メソッドに1以上の引数の指定をすると

import re
m = re.search(r'a(.*)c','abc123DEF')
m.group(1)
=> 'b'

 1なら1番目のキャプチャに、2なら2番目のキャプチャにマッチした値が得られる。

 

re.findall()関数 正規表現にマッチする全ての箇所を取得

下記の例では2文字以上の単語を抽出

import re
re.findall(r'\w{2,}','This is a pen')
=> ['This', 'is', 'pen']

 \wはUnicodeで単語の一部になり得る文字にマッチ。

その他、空白文字にマッチする「\s」などもある。

 

re.sub関数 正規表現にマッチする箇所を置換

import re
re.sub(r'\w{2,}','That','This is a pen')
=> 'That That a That'

 第3引数の文字列の第1引数の正規表現にマッチする箇所を全て、第2引数の文字列に置換する。

上記では、2文字以上の単語を全て第2引数に置換

 

 

こんな感じかな・・・。

個人的なメモなので悪しからず。。。 

 

 

参考文献 

こちらの本に詳しく載ってます。