この記事では、Pythonで正規表現を使う方法を解説します。
世界には様々な数字や文字で溢れいていますが、文字のパターンによってそれが何を表しているかわかる場合があります。(電話番号や郵便番号など)
そんな文字列は正規表現を使うことで簡単に抜き出すことができます。また、文字列から複雑な条件で必要な部分のみを抜き出すことも可能です。
それでは、正規表現の使い方を見ていきましょう!
正規表現とは?
正規表現(せいきひょうげん)とは、文字列の集合を一つの文字列で表現する方法で「正則表現(せいそくひょうげん)」とも呼ばれます。
正規表現を使って書かれた文字列を「パターン」と呼ぶ。
文字列の集合という言い方をしていますが、ここは数字ならなんでも、ここはA~Zの3文字、というように色々な条件を指定した文字列を表現できるということです。
例えば、郵便番号は「○○○-○○○○」という形で表現されますが、正規表現を使えば全ての郵便番号に一致する文字列を1つの文字列で表現することができます。
パターンが文字列と一致することを「マッチ」すると言う。
このように、正規表現を使うことで特定の形の文字列を1つの文字列で表現することができます。
正規表現の書き方を学ぶ前に...
パターンを作成するだけでは、実際にどんな文字列にマッチするかわからないのでre
モジュールのmatch()
メソッドを使ってどんな文字列を表現できているかを都度で確認していきます。
import re
re.match(pattern, string, flags)
match()
メソッドは、string
引数(文字列)の先頭からpattern
引数(正規表現)にマッチした場合にマッチオブジェクトを返し、マッチしなかった場合はNone
が返されます。
ここでは、難しく考える必要はないので「パターンにマッチした文字列を確認できるメソッド」と思っておいてください。
正規表現を使って複雑な文字列を操作する方法【reモジュールの使い方】
正規表現の書き方
正規表現は、文字列中に様々な特殊文字を記述することで表現できます。
まずは、「abc」にマッチする簡単なパターンを作成してみます。
import re
# パターン
pattern = 'abc'
# 文字列
s = 'abcdef'
# マッチ
match = re.match(pattern, s)
if match is None:
print('マッチしなかった')
else:
# 出力
print(f'文字列: {match.string}, マッチ: {match.group()}')
実行結果
文字列: abcdef, マッチ: abc
では次は、「a」から始まって「c」で終わり、間にはなんでもいいから1文字だけ記述されるパターンを作成します。
import re
# パターン
pattern = 'a.c'
# 文字列
s = 'abcdef'
# マッチ
match = re.match(pattern, s)
if match is None:
print('マッチしなかった')
else:
# 出力
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の正規表現の書き方について解説しました。
正規表現は、いろんな記号を使って見た目がゴチャゴチャしているので慣れないと難しく感じるかもしれませんが、単純なパターンなら簡単に作成できます。
Pythonで正規表現を使うには、re
モジュールを使います。
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ