Python

【Python】正規表現の使い方

この記事では、Pythonで正規表現を使う方法を解説します。

正規表現とは

正規表現(せいきひょうげん)とは、文字列の集合を一つの文字列で表現する方法です。「正則表現(せいそくひょうげん)」とも呼ばれます。

文字列の集合という言い方をしていますが、ここは数字ならなんでも、ここはA~Zの3文字、というように色々なパターンを指定した文字列を表現できるということです。

例えば、HTMLの見出しであるh2タグやh3タグで囲まれた部分のみを抜き出したい場合、通常、h2とh3に対しての条件を定義する必要があるが、正規表現を使えばhに2か3が付いているタグに囲まれた部分を抜き出すことができます。

このように正規表現を使うことで、複雑なパターンの文字列を1つの文字列で表現することができます。

正規表現の書き方

正規表現は、文字列中に様々な特殊文字を記述することで表現できます。

正規表現を確認する

reモジュールのmatchメソッドを使って、どんな文字列を表現できているかを確認しながら見てきましょう❗️

import re

re.match(pattern, string, flags)

matchメソッドは、string引数(文字列)の先頭から、pattern引数(正規表現)にマッチした場合にマッチオブジェクトを返します。

ここでは、難しく考える必要はないので「正規表現にマッチした文字列を確認できるメソッド」と思っておいてください。

パターン作成

まずは「abc」にマッチするパターンを作成してみます。

import re

# パターン
pattern = 'abc'

match = re.match(pattern, 'abcdef')

print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: abcdef, マッチした部分: abc

では次は「a」から始まって「c」で終わり、間にはなんでもいいから1文字だけ記述されるパターンを作成します。

import re

# パターン
pattern = 'a.c'

match = re.match(pattern, 'abcdef')

print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: abcdef, マッチした部分: abc

「.」は任意の1文字にマッチする特殊文字です。正規表現はこのような特殊文字を使って表現されます。

正規表現の特殊文字

Pythonで使用される特殊文字には以下のようなものがあります。

文字 説明 等価
. 任意の1文字 a.c
^ 文字列の先頭 \A ^abc
$ 文字列の末尾 \Z abc$
* 0回以上の繰り返し abc*
+ 1回以上の繰り返し abc+
? 0回か1回 abc?
*?, +?, ?? 最小マッチ
{m} m回の繰り返し a{3}
{m, n} m~n回の繰り返し(最大マッチ) a{3, 5}
{m, n}? m~n回の繰り返し(最小マッチ) a{3, 5}?
\ 特殊文字をエスケープ \^abc\^
[] 文字の集合 [abc]
| または a | b
() グループ化 (.)(.)
\number numberで指定したグループの中身 (<.+?>)\1
\A 文字列の先頭 ^ \Aabc
\b 空文字列(先頭または末尾) r’\bfoo\b’
\B 空文字列(先頭または末尾以外) ‘py\B’
\d 任意の10進数数字 [0-9] \d{3}-\d{4}
\D 10進数数字以外 [^0-9]
(\D+?) (\D+)
\s 空白文字 [\t\n\r\f\v]
.+\s.+
\S 空白文字以外 [^\t\n\r\f\v]
\d \S \d = \d
\w 英数字およびアンダースコア [a-zA-Z0-9_]
\w+
\W 英数字およびアンダースコア以外 [^a-zA-Z0-9_]
\Wabc\W
\Z 文字列の末尾 $ abc\Z

参考正規表現のシンタックス

グループ化

()を使うことでグループ化することができます。グループ化して何が嬉しいかというと、グループ化した部分ごとに文字列を取得できることです。

例えば「name=山田太郎」というような文字列を抜き出す場合、「name」と「山田太郎」は別々に取得できた方が便利です。

import re

pattern = '(.+?)=(.+)'

match = re.match(pattern, 'name=山田太郎')
print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: name=山田太郎, マッチした部分: name=山田太郎

print(f'section: {match.group(1)}, value: {match.group(2)}')
>> section: name, value: 山田太郎

(?P<グループ名>)でグループ名を指定することもできます。

import re

pattern = '(?P<section>.+?)=(?P<value>.+)'

match = re.match(pattern, 'name=山田太郎')
print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: name=山田太郎, マッチした部分: name=山田太郎

# グループ名でアクセスできる
print(f'section: {match.group("section")}, value: {match.group("value")}')
>> section: name, value: 山田太郎

最小マッチ

「.*」や「.+」を使う場合、思わぬ大きな箇所にマッチしてしまう場合があります。そんな時は「?」を付けて最小マッチで的確に欲しい箇所を抜き出しましょう❗️

import re

string = '[aaa]bbb]'
pattern = '\[.+\]'

match = re.match(pattern, string)
print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: [aaa]bbb], マッチした部分: [aaa]bbb]

# ?を付ける
pattern = '\[.+?\]'

match = re.match(pattern, string)
print(f'渡された文字列: {match.string}, マッチした部分: {match.group()}')
>> 渡された文字列: [aaa]bbb], マッチした部分: [aaa]

まとめ

この記事では、Pythonの正規表現の書き方について解説しました。

正規表現は、いろんな記号を使って見た目がゴチャゴチャしているので、慣れないと難しく感じるかもしれませんが、単純なパターンなら簡単に作成できます。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

最短3か月でエンジニア転職『DMM WEBCAMP COMMIT』