Pythonの正規表現は微妙に他の言語と異なるところがあり、特に2.7系では文字コードの扱いで注意が必要です。
まずすべてstr型なら普通に実行されます。
import re testStr = "あいうえお" p = re.compile("あ") print p.sub("か",testStr)
結果
かいうえお
次に全てunicodeでもうまくいきます。
# -*- coding: utf-8 -*- import re testStr = u"あいうえお" p = re.compile(u"あ") print p.sub(u"か",testStr)
結果
かいうえお
unicodeとstr型を一つにまとめようとするとエラーになります。
# -*- coding: utf-8 -*- import re testStr = u"あいうえお" p = re.compile(u"あ") print p.sub("か",testStr)
結果
Traceback (most recent call last): File "regExp.py", line 9, in <module> print p.sub("か",testStr) UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
unicode型からstr型を検索したり、またはその逆をすると検索されません。
import re testStr = "あいうえお" #str p = re.compile(u"あ") #unicode print p.sub("か",testStr)
結果
あいうえお
これはエラーにはならないので、結構見つけにくいバグになることがあります。 かならず同じ型でそろえるようにしましょう。 日本語があるならunicodeにそろえるのがおすすめです。
また正規表現検索のメソッドは基本的にre.compleでオブジェクトを作るのと、reからメソッドを呼び出す方法と二つのやり方で実行できます。
import re testStr = u"あいうえお" p = re.compile(u"あ") print p.sub(u"か",testStr) print re.sub(u"あ", u"か", testStr)
結果
かいうえお かいうえお
検索パターンを何度も使い回すなら、コンパイルした方がよいでしょう。 パターンも動的に変えるなら、reから呼び出すと便利です。
以下では正規表現の基本的な書式は既知のものとし、pythonでの使い方を中心に解説します。
置換はすでに上の説明で使った、subとsubnがあります。 subは単純な置換、subnは置換した数とのタプルを返します。
# -*- coding: utf-8 -*- import re testStr = u"あいあいうえお" p = re.compile(u"あ") print p.sub(u"か",testStr) for n in p.subn( u"か", testStr): print n
結果
かいかいうえお かいかいうえお 2
()でのグループ化、それを参照するのにも対応。
# -*- coding: utf-8 -*- import re testStr = u"あいあいうえお" p = re.compile(u"(.)あ") print p.sub(u'\\1か',testStr)
結果
あいかいうえお
上の例では「あ」の前に文字のあるときだけ、その「あ」を「か」に変更しています。ここでもし「\\1」がないと、2文字が「か」になるため、結果は「あかいうえお」となり、「い」が消えてしまいます。グループが複数あれば「\\2」「\\3」などとして参照できます。
pythonの正規表現検索は以下の物があります
メソッド | 特長 |
match | 文字列先頭のみにマッチする。なければNoneを返す。 |
search | マッチした場所を返す。なければNoneを返す。 |
findall | マッチした部分をリストにして返す。 |
finditer | マッチした部分のMatchオブジェクトのイテレーターを返す。 |
matchとsearchは特に文字列の存在チェックなどによく使います。
# -*- coding: utf-8 -*- import re testStr = u"あいうえお" checkStr = u"うえお" if re.search(checkStr, testStr): print "searched" if re.match(checkStr, testStr): print "matched"
結果
searched
この例では正規表現がないので、「in」を使ってもよいです。 「match」は先頭のみにヒットするので、「search」に比べると使用頻度は少なめです。
ヒットした文字列が必要なら「findall」を使います。 より詳しい情報が必要なら開始、終了位置などが入ったMatchオブジェクトを返す「finditer」を使います。
# -*- coding: utf-8 -*- import re testStr = u"にわにはにわにわとりがいる" checkStr = u"にわ" resultList = re.findall(checkStr,testStr) for r in resultList: print r print for r in re.finditer(checkStr,testStr): print r.group() #検索文字列 print r.start(),r.end() #開始位置、終了位置 print r.span() #開始、終了位置のタプル
結果
にわ にわ にわ にわ 0 2 (0, 2) にわ 4 6 (4, 6) にわ 6 8 (6, 8)