「正規表現…?」
Pythonを勉強していると「正規表現」という言葉が出てきますが、耳馴染みのない言葉なので多くの人が曖昧な理解で終えてしまいます。
しかし、もしあなたがWebスクレイピングやテキストのデータ処理を行うためにPythonを学んでいるのであれば、正規表現の知識は必須です!
If文で数十行書かなければならない処理が、正規表現を用いることで2,3行でかけてしまうということが頻繁にあります。
この記事では、コードの簡略化に欠かせない正規表現について、意味・種類・使い方などを解説します。
この記事を読んで、正規表現の基本をマスターしましょう!
AIやデータサイエンスを学びたくてPythonを学び始めたけど
「独学ではやっぱり限界がある」
と不安を感じた方にオススメしたいのが、Aidemy Premium Plan。
AIに関する幅広い種類の講座や徹底したコーチング指導が特徴です!
実務を見据えてPythonをがっつり学習していきたい方は、まずは無料の「オンライン相談」に参加してみてください。
Pythonの正規表現とは
正規表現とは、パターンで文字列を表現したものです。
例えば、あるWebページ内の電話番号の記載を探しているとします。
多くの方は、Ctrl+F(Windows)やcommand+F(Mac)というコマンドを知っているので、「電話番号」と入力して「電話番号と書かれている箇所」を探し、その近くに書いてある電話番号を見つけます。
しかしこの方法は、「電話番号」ではなく「tel」「問い合わせ先」など別の言葉で書かれているときには有効ではありません。
正規表現の「パターンで文字列を表現」とは、「○○○-○○○○-○○○○」といった文字がどのように配列されるかを指します。
「○○○-○○○○-○○○○」という並び(パターン)の文字列を探せば、サイト内の電話番号を隈なく見つけられそうですよね(もちろん、市外局番が2桁のときもありますが、正規表現は柔軟に対応できます)。
Pythonの正規表現の種類
正規表現では、「090–1234-5678」のような電話番号を「○○○-○○○○-○○○○」といったパターンで表せます。
実際のプログラムの際は、○ではなく数字の集合である「\d」で表現します。
すなわち、「○○○-○○○○-○○○○」は「\d\d\d-\d\d\d\d-\d\d\d\d」と表すことができます。
以下の表に、「\d」のような文字の集合(特殊シーケンス)をまとめました。
表現 | 意味 |
\d | 数字(0〜9) |
\D | 数字(0〜9)以外 |
\w | 文字・数字・下線 |
\W | 文字・数字・下線以外 |
\s | スペース・改行・タブ |
\S | スペース・改行・タブ以外 |
具体例は後ほど紹介します。
また、正規表現にはメタ文字とよばれる、特殊な働きをする文字があります。
メタ文字の種類や意味、具体例は以下の通りです。
メタ文字 | 意味 | 具体例 |
? | 直前の文字・グループの0回か1回の出現 | (wo)?man woはあってもなくても良い |
* | 直前の文字・グループの0回以上の繰り返し | 321* |
+ | 直前の文字・グループの1回以上の繰り返し | 321+ |
{n} | 直前の文字・グループのn回の繰り返し | \d{3} |
{n,m} | 直前の文字・グループのn〜m回の繰り返し | \d{2,3} |
{n,} | 直前の文字・グループのn回以上の繰り返し | a{3} |
{,m} | 直前の文字・グループの0〜m回の繰り返し | a{3} |
[ ] | [ ]内の任意の1文字とマッチ | [aeiou] |
[^ ] | [ ]内の文字以外の任意の1文字とマッチ | [^aeiou] |
. | 改行文字以外の任意の1文字とマッチ | .a |
^ | 文字列の先頭とマッチ | ^I |
$ | 文字列の末尾とマッチ | you$ |
| | または | dog|cat |
Pythonの正規表現の基本的な使い方(パターンマッチング)
Pythonでは、以下手順で正規表現を用いたパターンマッチングができます。
正規表現モジュールをインポートする
Pythonで正規表現を使うには、reモジュールが必要になります。
reモジュールのインポートはこのようにしてできます。
[code language=”python”]import re[/code]
これで、正規表現に必要な道具が揃ったことになります。
re.compile()関数を用い、Regexオブジェクトを生成する
re.compile()関数に文字列パターンを渡すと、渡したパターンの情報を持ったRegexオブジェクトが帰ってきます。
[code language=”python”]phone_regex = re.compile(r’\d\d\d-\d\d\d\d-\d\d\d\d’) # rを書くことで\を文字として扱う[/code]
ここでは、「○○○-○○○○-○○○○」型の電話番号のパターンを渡しました。
Regexオブジェクトのsearch()メソッドに、検索対象の文字列を渡す
先ほど取得したRegexオブジェクトにsearch()メソッドを呼び出して、検索対象となる文字列を引数として渡します。
パターンが見つかると、Matchオブジェクトが返されます。
Matchオブジェクトにはmoを用いるのが一般的です。
[code language=”python”]mo = phone_regex.search(‘私の名前は長嶋貞治です。42歳です。電話番号は090-1234-5678です。郵便番号は100-2345です。ご用がある方はこちらへどうぞ。よろしくお願いします。’)[/code]
Matchオブジェクトにgroup()メソッドを呼び出す
最後に、Matchオブジェクトにgroup()メソッドを呼び出すことで、マッチしたテキストが返されます。
[code language=”python”]print(‘電話番号: ‘, mo.group())[/code]
これで正規表現を用いたパターンマッチングは完了です。
ここで今までのプログラムをまとめて記載します。
[code language=”python”]import re
phone_regex = re.compile(r’\d\d\d-\d\d\d\d-\d\d\d\d’) # rを書くことで\を文字として扱う
mo = phone_regex.search(‘私の名前は長嶋貞治です。42歳です。電話番号は090-1234-5678です。郵便番号は100-2345です。ご用がある方はこちらへどうぞ。よろしくお願いします。’)
print(‘電話番号: ‘, mo.group())[/code]
パターンや検索対象のテキストを変えて実験してみてください。
複数個全て取得したい場合は、findall()メソッドを用いると、合致したパターン全てが入った文字列のリストが返ってきます。
Python正規表現の貪欲マッチ・非貪欲マッチ
(Meow){2,4}(意味: Meowを2~4回繰り返す)というパターンで、’MeowMeowMeowMeowMeow’という文字列とパターンマッチングした際、何が返ってくるでしょうか。
候補としては、’MeowMeow’、’MeowMeowMeow’、’MeowMeowMeowMeow’が挙げられます。
理論上はどれも正しいのですが、Pythonの正規表現では最大である4回繰り返した’MeowMeowMeowMeow’が返ってきます。
パターンマッチングの際、合致する候補が複数ある場合は、Pythonのデフォルトでは一番長い候補を返します。
このことを貪欲マッチといいます。
もし最も短いものとマッチさせたい(非貪欲マッチ)ときは、(Meow){2,4}の{}の後に?をつけましょう。
[code language=”python”]meow_text = ‘MeowMeowMeowMeowMeow’ # 検索対象のテキスト
meow_regex1 = re.compile(r'(Meow){2,4}’) # 貪欲マッチ
meow_regex2 = re.compile(r'(Meow){2,4}?’) # 非貪欲マッチ
mo1 = meow_regex1.search(meow_text) # 貪欲マッチ
mo2 = meow_regex2.search(meow_text) # 非貪欲マッチ
print(‘貪欲マッチ:’, mo1.group()) # 貪欲マッチ: MeowMeowMeowMeow
print(‘非貪欲マッチ:’, mo2.group()) # 非貪欲マッチ: MeowMeow
[/code]
Pythonの正規表現はテキスト処理に欠かせない
この記事ではPythonの正規表現について解説してきました。
学んでみてさらに感じたかと思いますが、正規表現はテキストの情報を検索するのに欠かせないものです。
そして書いてみないと分からないことも多いです。
ぜひたくさんプログラムを書いて、正規表現を身につけていきましょう!
参考: