今回の記事は正規表現と例についてをまとめします。
正規表現とは
文字列の集合を一つの文字列で表現する方法です。英語では、“regular expressions”(REs や regexes または regex patterns)と呼ばれています。文字列からe-mailや電話番号の検索、抽出、置換ができます。
正規表現で使用する特殊文字
正規表現は、いくつかの特別な文字“メタ文字”によって表現されます。例えば、「$」には、文字列の末尾という意味合いがあります。
メタ文字
メタ文字 | 説明 | 指定例 | 合致する | 合致しない |
. | 改行以外の任意の一文字 | a.c | abc | ac abbc |
^ | 文字列の先頭 | ^ab | abc | zab |
$ | 文字列の末尾 | ab$ | zab | abc |
* | 直前の文字の0回以上の繰り返し | ab* | a ab abb | aa ac |
+ | 直前の文字の1回以上の繰り返し | ab+ | ab abb | a |
? | 直前の文字の0回または1回 | ab? | a ab | abb |
{m} | 直前の文字のm回の繰り返し | a{2} | aa | a aaa |
{m,n} | 直前の文字のm回からn回の繰り返し | a{1,2} | a aa | aaa |
\ | 特殊文字のエスケープ | \. | . | a |
[文字の集合] | 集合の中の1文字 | [a-c] | a b c | d |
[^文字の集合] | 集合に含まれない1文字 | [^a-c] | d | a b c |
| | いずれか | a|b | a b | c |
() | グループ化 | (ab|cd) | ab cd | abc ac |
特殊シーケンス
バックスラッシュで始まる特殊シーケンスもあります。
特殊シーケンス | 説明 | 同義のパターン |
\d | 任意の数字 | ASCIIの場合、[0-9] |
\D | \d以外 | |
\s | 任意の空白文字 | ASCIIの場合、[ \t\n\r\f\v] |
\S | \s以外 | |
\w | 任意のUnicode単語文字 | ASCIIの場合、[a-xA-Z0-9_] |
\W | \w以外 | |
\A | 文字列の先頭 | ^ |
\Z | 文字列の末尾 | $ |
reモジュール
文字列に対して正規表現を使うには、reモジュールはPythonの標準ライブラリで提供されており、以下のimport文で使用することができます。
import re
ここからは実際に文字列を抽出することが出来る関数やメソッドを紹介していきます。
match関数
match関数は、検索対象の文字列の先頭に抽出ワードが存在するか判定します。第一引数に抽出する正規表現、第二引数に検索対象の文字列を指定します。対象が存在しない場合はNoneを返し、存在する場合はmatchオブジェクトが返ります。
# 郵便番号を検索する import re address = "160-0023 東京都新宿区西新宿1丁目15−13" postCode = re.match('[0-9]{3}-[0-9]{4}' , address) print (postCode)
<_sre.SRE_Match object; span=(0, 8), match='160-0023'>
search関数
search関数は検索対象の文字列の先頭から最後までを検索し、抽出ワードが存在するか判定します。第一引数に抽出する正規表現、第二引数に検索対象の文字列を指定します。対象が存在しない場合はNoneを返し、存在する場合はmatchオブジェクトが返ります。match関数との違いは、searchは全文であり、matchは先頭だけの確認になります。
# 郵便番号を検索する import re address = "160-0023 東京都新宿区西新宿1丁目15−13" postCode = re.search('[0-9]{3}-[0-9]{4}' , address) print (postCode)
<_sre.SRE_Match object; span=(0, 8), match='160-0023'>
findall関数
findall関数は検索対象の文字列の先頭から最後までを検索し、存在する正規表現の全てを取得して文字列のリストで返します。第一引数に抽出ワード、第二引数に検索対象の文字列を指定します。
# URLを出力する
import re
html = """
<html>
<head></head>
<body>
<div id="item">
<a href="https://website.com/products/mems/7913/"></a>
</div>
<div id="item">
<a href="https://website.com/products/kids/8567/"></a>
</div>
</body>
</html>
"""
url_list = re.findall('https://website.com/products/[a-z]+/[0-9]{4}/' , html)
if urlList:
print (url_list)
['https://website.com/products/mems/7913/', 'https://website.com/products/kids/8567/']
find関数
findメソッドは文字列型のメソッドで、文字列を検索するときに使用します。検索対象の文字列の中にあるインデックス番号を示しています。
# 言葉と探す import re address = "160-0023 東京都新宿区西新宿1丁目15−13" city = address.find(‘東京’) print(city)
9
split関数
split()はパターンにマッチした部分で文字列を分割し、リストにして返す。
# 住所を分ける import re s_nums = '160-0023 東京都新宿区西新宿1丁目15−13' pat = '(...??[都道府県])((?:旭川|伊達|石狩|盛岡|奥州|田村|南相馬|那須塩原|東村山|武蔵村山|羽村|十日町|上越|富山|野々市|大町|蒲郡|四日市|姫路|大和郡山|廿日市|下>松|岩国|田川|大村|宮古|富良野|別府|佐伯|黒部|小諸|塩尻|玉野|周南)市|(?:余市|高市|[^市]{2,3}?)郡(?:玉村|大町|.{1,5}?)[町村]|(?:.{1,4}市)?[^町]{1,4}?区|.{1,7}?[市町村])(.+)' print(re.split(pat, s_nums))
['160-0023', ' 東京都', '新宿区', '西新宿1丁目15−13', '']
sub関数
文字列を置換する場合は、sub関数を使います。
# 電話番号をを隠す(最初) import re phoneNo = """\ 03-6380-6263 03-5291-9211 03-3226-1111 ... """ phoneNo2 = re.sub('^[0-9]{2}-[0-9]{4}-[0-9]{4}', "**-****-****", phoneNo) print(phoneNo2)
**-****-****
03-5291-9211
03-3226-1111
MULTILINEオプション
一行一行のチェックを行うには、re.MULTILINE を指定します。
# 電話番号をを隠す(全て) import re phoneNo = """\ 03-6380-6263 03-5291-9211 03-3226-1111 ... """ phoneNo2 = re.sub('^[0-9]{2}-[0-9]{4}-[0-9]{4}', "**-****-****", phoneNo, flags=re.MULTILINE) print(phoneNo2)
**-****-****
**-****-****
**-****-****
DOTALLオプション
DOTALL (Dot Matches Line Breaks)
複数行にわたる文字列をマッチさせるには、「re.DOTALL」を指定します。
# htmlのBody内の内容を出力する
import re
html = """
<html>
<head></head>
<body>
Body content
</body>
</html>
"""
body = re.findall('<body>*.*</body>', html, flags=re.DOTALL)
print(body)
['<body>\nBody content\n</body>']
IGNORECASEオプション
ignoreCase プロパティは、”i” フラグが正規表現で使われているかどうかを示します。ignoreCase は、正規表現インスタンスごとの読み取り専用プロパティです。ignoreCase は、個々の正規表現オブジェクトのプロパティです。
# 住所の内容を出力する address = "25 Madison Avenue, New York, NY" city = re.findall('new york', address, flags=re.IGNORECASE) print(city)
['New York']
まとめ
今回は Python における正規表現の使い方について説明しました。正規表現は複雑な文字列の処理を行うときに非常に便利な方法です。Python の re モジュールを使用して様々な正規表現パターンを処理することができます。ただしpandasはまたメソッドとして別で存在しているためまた紹介してきます。
Pythonの正規表現資料:
https://docs.python.org/ja/3/library/re.html