正規表現
正規表現がいまいち飲み込めないので、確認用のメモ
使用環境
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)(原文)pattern の string へのマッチのうち、重複しない全てのマッチを文字列のリストとして返します。 string は左から右へと走査され、マッチは見つかった順番で返されます。パターン中に何らかのグループがある場合、グループのリストを返します。グループが複数定義されていた場合、タプルのリストになります。他のマッチの開始部分に接触しないかぎり、空のマッチも結果に含められます。
re.
sub
(pattern, repl, string, count=0, flags=0)(原文)string 内で、pattern のマッチを repl で置き換えた文字列を返します。パターンが重複している場合は、一番左のマッチのみを置き換えます。パターンが見つからなければ string を変更せずに返します。repl は文字列でも関数でも構いません; 文字列の場合、バックスラッシュエスケープは処理されます。すなわち、
\n
は単一の改行文字に変換され、\r
はキャリッジリターンに変換されます。\&
のような未知のエスケープは処理されず、そのままにされます。\6
のような後方参照は、パターンのグループ 6 とマッチした部分文字列で置換されます。
実際に使用してみる
正規表現のパターンには\(バックスラッシュ)が頻発するため、面倒なので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引数に置換
こんな感じかな・・・。
個人的なメモなので悪しからず。。。
参考文献
こちらの本に詳しく載ってます。
Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-
- 作者: 加藤耕太
- 出版社/メーカー: 技術評論社
- 発売日: 2016/12/16
- メディア: 大型本
- この商品を含むブログ (2件) を見る