Pythonにおいて、文字列を検索する際に、正規表現を使用する方法について、紹介します。
本記事では、以下の内容を紹介しています。
この記事で分かること
- 正規表現とは
- 正規表現の基本的な使用方法
◆reモジュールの関数について◆
- match( ) : 文字列の先頭がマッチするか判定
- search( ) : 先頭に限らずマッチするか判定
- fullmatch( ) : 文字列全体がマッチするか判定
- findall( ) : マッチした文字列をリストで取得
- finditer( ) : マッチした文字列をイテレータで取得
- sub( ) : マッチした文字列を置換
- split( ) : パターンで文字列を分割
◆メタ文字の使用例◆
- . : 任意の1文字
- * : 直前のパターンを0回以上繰り返し
- + : 直前のパターンを1回以上繰り返し
- ? : 直前のパターンを0回または1回繰り返し
- {m} : 直前のパターンをm回繰り返し
- {m,n} : 直前のパターンをm~n回繰り返し
- [ ] : 文字の集合を指定
- ( ) : グループ化
- A|B : AかBのどちらか
- ^ : 文字列の先頭
- $ : 文字列の末尾
スポンサーリンク
正規表現とは
正規表現とは、文字列をパターンで表現する記述方法です。
正規表現を用いることで、指定したパターンに当てはまる文字列を検索することができます。
Pythonの標準ライブラリである、"reモジュール"を用いることで、正規表現を扱うことができます。
以降の項で、Pythonにおける正規表現の基本的な使用方法について、紹介します。
スポンサーリンク
【Python】正規表現の基本的な使用方法
Pythonにおける、正規表現の基本的な使用方法について紹介します。
以下の3つについて、順番に紹介します。
- reモジュールで使用できる関数について
- 正規表現のメタ文字について
- マッチオブジェクトについて
reモジュールで使用できる関数について
Pythonの標準ライブラリである、"reモジュール"を用いることで、正規表現を扱うことができます。
reモジュールには、使用できる関数が複数あり、文字列パターンの検索方法を指定できます。
reモジュールで使用できる関数としては、次のものがあります。
関数 | 説明 |
---|---|
match( ) | 文字列の先頭がマッチするか判定 |
search( ) | 先頭に限らずマッチするか判定 |
fullmatch( ) | 文字列全体がマッチするか判定 |
findall( ) | マッチした文字列をリストで取得 |
finditer( ) | マッチした文字列をイテレータで取得 |
sub( ) | マッチした文字列を置換 |
正規表現のメタ文字について
検索する文字列のパターンは、"メタ文字"を用いて指定します。
Pythonの "reモジュール" で使用できるメタ文字には、次のものがあります。
メタ文字 | 説明 | 指定例 | マッチする例 | マッチしない例 |
---|---|---|---|---|
. | 任意の1文字 (改行は含まない) | a.c | abc,acc,a1c | abb,abbc |
* | 直前のパターンを0回以上繰り返し | ab* | a,ab,abb | aa,bb |
+ | 直前のパターンを1回以上繰り返し | ab+ | ab,abb | a,aa,bb |
? | 直前のパターンを0または1回繰り返し | ab? | a,ab | abb |
{m} | 直前のパターンをm回繰り返し | a{2} | aa | a,aaa |
{m,n} | 直前のパターンをm~n回繰り返し | a{2,3} | aa,aaa | a,aaaa |
[ ] | 文字の集合を指定。[ ]内に指定した文字のうち、どれかを含む | [a-c] | a,b,c | d,e,f |
( ) | グループ化 | (abc)+ | abc,abcabc | a,ab |
A | B | AかBのどちらかのパターン | a|b | a,b | c,d |
^ | 文字列の先頭 | ^abc | abcdef | defabc |
$ | 文字列の末尾 | abc$ | defabc | abcdef |
この表以外にも使用できるメタ文字があります。
詳細は、Pythonの公式ドキュメントを参考にしてみてください。
マッチオブジェクトについて
reモジュールの関数であるmatch( )やsearch( )は、マッチオブジェクトを返します。
マッチオブジェクトのメソッドを実行することで、マッチした文字列や位置を取得できます。
Pythonのマッチオブジェクトのメソッドには、次のものがあります。
メソッド | 説明 |
---|---|
start( ) | マッチした文字列の開始位置を取得 |
end( ) | マッチした文字列の終了位置を取得 |
span( ) | マッチした文字列の開始位置と終了位置を取得 |
group( ) | マッチした文字列を取得 |
正規表現の基本的な使用例
正規表現の基本的な使用例を紹介します。
以下、match( )関数を用いて文字列を検索するサンプルコードです。
### match()関数で検索
import re
s = r'abcde, 12345, a123e'
res = re.match(r'a...e', s)
print(type(res))
# <class 're.Match'>
print(res)
# <re.Match object; span=(0, 5), match='abcde'>
print(res.start())
#0
print(res.group())
#abcde
> res = re.match(r'a…e', s)
reモジュールのmatch( )関数を用いて、パターン "a...e" に一致する文字列を検索しています。
> print(type(res))
> # <class 're.Match'>
変数 res はマッチオブジェクトです。
> print(res.start())
> #0
マッチオブジェクトのメソッドstart()を用いて、文字列の開始位置を取得しています。
> print(res.group())
> #abcde
マッチオブジェクトのメソッドgroup()を用いて、マッチした文字列を取得しています。
スポンサーリンク
reモジュールの関数の使用方法
ここからは、reモジュールの関数について、サンプルコードを交えながら紹介します。
以下の関数の使用方法について、順番に紹介します。
- match( ) : 文字列の先頭がマッチするか判定
- search( ) : 先頭に限らずマッチするか判定
- fullmatch( ) : 文字列全体がマッチするか判定
- findall( ) : マッチした文字列をリストで取得
- finditer( ) : マッチした文字列をイテレータで取得
- sub( ) : マッチした文字列を置換
- split( ) : パターンで文字列を分割
match( ) : 文字列の先頭がマッチするか判定
match( )関数は、文字列の先頭がパターンにマッチするかを判定する関数です。
書き方
re.match( パターン, 検索対象の文字列 )
以下、サンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.match(r'a...e', s)
print(res)
# <re.Match object; span=(0, 5), match='abcde'>
文字列の先頭がパターンと一致しない場合には、"None" が返されます。
import re
s = r'12345, abcde, a123e'
res = re.match(r'a...e', s)
print(res)
# None
search( ) : 先頭に限らずマッチするか判定
search( )関数は、文字列がパターンにマッチするかを判定する関数です。
match( )関数とは異なり、文字列の先頭に限らずパターンとマッチするか判定できます。
書き方
re.search( パターン, 検索対象の文字列 )
以下、サンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.search(r'a...e', s)
print(res)
# <re.Match object; span=(0, 5), match='abcde'>
文字列の先頭以外でも、パターンにマッチするか判定されます。
import re
s = r'12345, abcde, a123e'
res = re.search(r'a...e', s)
print(res)
# <re.Match object; span=(7, 12), match='abcde'>
fullmatch( ) : 文字列全体がマッチするか判定
fullmatch( )関数は、文字列全体がパターンにマッチするかを判定する関数です。
書き方
re.fullmatch( パターン, 検索対象の文字列 )
以下、サンプルコードです。
import re
s = r'abcde'
res = re.fullmatch(r'a...e', s)
print(res)
# <re.Match object; span=(0, 5), match='abcde'>
検索対象の文字列が、1字でもパターンと異なる場合には、"None"が返されます。
import re
s = r'abcdef'
res = re.fullmatch(r'a...e', s)
print(res)
# None
スポンサーリンク
findall( ) : マッチした文字列をリストで取得
findall( )関数を用いることで、マッチした文字列をリストで取得することができます。
書き方
re.findall( パターン, 検索対象の文字列 )
以下、サンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.findall(r'a...e', s)
print(res)
# ['abcde', 'a123e']
文字列の先頭以外でも、パターンにマッチするか判定されます。
import re
s = r'12345, abcde, a123e'
res = re.findall(r'a...e', s)
print(res)
# ['abcde', 'a123e']
finditer( ) : マッチした文字列をイテレータで取得
finditer( )関数を用いることで、マッチした文字列をイテレータで取得することができます。
書き方
re.finditer( パターン, 検索対象の文字列 )
イテレータは、そのままprint( )を用いただけでは、中身を確認できません。
for文を用いて、1つずつ取り出すことで、中身を確認できます。
以下、サンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.finditer(r'a...e', s)
print(res)
# <callable_iterator object at 0x0000025F80C43978>
for r in res :
print(r)
# <re.Match object; span=(0, 5), match='abcde'>
# <re.Match object; span=(14, 19), match='a123e'>
文字列の先頭以外でも、パターンにマッチするか判定されます。
import re
s = r'12345, abcde, a123e'
res = re.finditer(r'a...e', s)
print(res)
# <callable_iterator object at 0x0000024BA82E22B0>
for r in res :
print(r)
# <re.Match object; span=(7, 12), match='abcde'>
# <re.Match object; span=(14, 19), match='a123e'>
findall( )関数では、一致した文字列のみ取得できましたが、
finditer( )関数では、一致した文字列の位置も併せて取得できます。
sub( ) : マッチした文字列を置換
sub( )関数を用いることで、マッチした文字列を置換できます。
書き方
re.sub( パターン, 置換後の文字列, 検索対象の文字列, 最大置換個数)
最大置換個数は省略可能です。
以下、サンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.sub(r'a...e', r'xxx', s)
print(res)
# xxx, 12345, xxx
文字列の先頭以外でも、パターンにマッチするか判定されます。
import re
s = r'12345, abcde, a123e'
res = re.sub(r'a...e', r'xxx', s)
print(res)
# 12345, xxx, xxx
最大置換個数を1個指定したサンプルコードです。
import re
s = r'abcde, 12345, a123e'
res = re.sub(r'a...e', r'xxx', s, 1)
print(res)
# xxx, 12345, a123e
split( ) : パターンで文字列を分割
split( )関数を用いることで、パターンで文字列を分割できます。
書き方
re.split( パターン, 検索対象の文字列, 最大分割個数)
最大分割個数は省略可能です。
以下、サンプルコードです。
import re
s = r'123abcde456a123e789'
res = re.split(r'a...e', s)
print(res)
# ['123', '456', '789']
スポンサーリンク
メタ文字の使用例
ここからは、正規表現で使用できるメタ文字について、サンプルコードを交えながら使用方法を紹介します。
下表のメタ文字について、順番に紹介します。
メタ文字 | 説明 | 指定例 | マッチする例 | マッチしない例 |
---|---|---|---|---|
. | 任意の1文字 (改行は含まない) | a.c | abc,acc,a1c | abb,abbc |
* | 直前のパターンを0回以上繰り返し | ab* | a,ab,abb | aa,bb |
+ | 直前のパターンを1回以上繰り返し | ab+ | ab,abb | a,aa,bb |
? | 直前のパターンを0または1回繰り返し | ab? | a,ab | abb |
{m} | 直前のパターンをm回繰り返し | a{2} | aa | a,aaa |
{m,n} | 直前のパターンをm~n回繰り返し | a{2,3} | aa,aaa | a,aaaa |
[ ] | 文字の集合を指定。[ ]内に指定した文字のうち、どれかを含む | [a-c] | a,b,c | d,e,f |
( ) | グループ化 | (abc)+ | abc,abcabc | a,ab |
A | B | AかBのどちらかのパターン | a|b | a,b | c,d |
^ | 文字列の先頭 | ^abc | abcdef | defabc |
$ | 文字列の末尾 | abc$ | defabc | abcdef |
. : 任意の1文字
以下、サンプルコードです。
import re
s = r'abc, acc, abbc'
res = re.findall(r'a.c', s)
print(res)
# ['abc', 'acc']
"abbc" は、aとcの間に2文字あるので、パターンには一致しません。
* : 直前のパターンを0回以上繰り返し
以下、サンプルコードです。
import re
s = r'a, b, ab, aa, bb, abb, aab'
res = re.findall(r'ab*', s)
print(res)
# ['a', 'ab', 'a', 'a', 'abb', 'a', 'ab']
+ : 直前のパターンを1回以上繰り返し
以下、サンプルコードです。
import re
s = r'a, b, ab, aa, bb, abb, aab'
res = re.findall(r'ab+', s)
print(res)
# ['ab', 'abb', 'ab']
? : 直前のパターンを0回または1回繰り返し
以下、サンプルコードです。
import re
s = r'a, b, ab, aa, bb, abb, aab'
res = re.findall(r'ab?', s)
print(res)
# ['a', 'ab', 'a', 'a', 'ab', 'a', 'ab']
{m} : 直前のパターンをm回繰り返し
以下、サンプルコードです。
import re
s = r'a, b, ab, aa, bb, abb, aab, aaa, aaaa'
res = re.findall(r'a{2}', s)
print(res)
# ['aa', 'aa', 'aa', 'aa', 'aa']
{m,n} : 直前のパターンをm~n回繰り返し
以下、サンプルコードです。
import re
s = r'a, b, ab, aa, bb, abb, aab, aaa, aaaa'
res = re.findall(r'a{2,3}', s)
print(res)
# ['aa', 'aa', 'aaa', 'aaa']
[ ] : 文字の集合を指定
以下、サンプルコードです。
import re
s = r'123abcde456a123e789'
res = re.findall(r'[a-z]+', s)
print(res)
# ['abcde', 'a', 'e']
ハイフン'-'を用いると、文字や数値の範囲を指定できます。
[a-z]+ とすることで、aからzまでの小文字のアルファベットのうちいずれか を、1回以上繰り返す という意味になります。
こちらは、3~5回繰り返された小文字のアルファベットを抽出するサンプルコードです。
import re
s = r'123abcde456a123e789'
res = re.findall(r'[a-z]{3,5}', s)
print(res)
# ['abcde']
( ) : グループ化
以下、サンプルコードです。
import re
s = r'123abcabc456abc789abcabcabc123'
res = re.finditer(r'(abc)+', s)
print(res)
# <callable_iterator object at 0x0000025F80D370F0>
for r in res :
print(r)
# <re.Match object; span=(3, 9), match='abcabc'>
# <re.Match object; span=(12, 15), match='abc'>
# <re.Match object; span=(18, 27), match='abcabcabc'>
(abc)+ とすることで、abcが1回以上繰り返された場合に、マッチするようになります。
A|B : AかBのどちらか
以下、サンプルコードです。
import re
s = r'aa ab, ac, bc, bb, cc'
res = re.finditer(r'(a|b)c', s)
print(res)
# <callable_iterator object at 0x0000025F80D37198>
for r in res :
print(r)
# <re.Match object; span=(7, 9), match='ac'>
# <re.Match object; span=(11, 13), match='bc'>
^ : 文字列の先頭
"^"を記載することで、文字列の先頭がパターンに一致するかを判定できます。
import re
s = r'abcde12345'
res = re.search(r'^abc', s)
print(res)
# <re.Match object; span=(0, 3), match='abc'>
文字列の先頭がパターンに一致しない場合は、Noneが返されます。
import re
s = r'12345abcde'
res = re.search(r'^abc', s)
print(res)
# None
なお、" ^ "は、集合と併せて記述した場合は、補集合を表す記号になるので、注意してください。
import re
s = r'123abcde456a123e789'
res = re.findall(r'[^a-z]+', s)
print(res)
# ['123', '456', '123', '789']
$ : 文字列の末尾
"$"を記載することで、文字列の末尾がパターンに一致するかを判定できます。
import re
s = r'123abc'
res = re.search(r'abc$', s)
print(res)
# <re.Match object; span=(3, 6), match='abc'>
文字列の末尾がパターンに一致しない場合は、Noneが返されます。
import re
s = r'abc123'
res = re.search(r'abc$', s)
print(res)
# None
正規表現に関しては、他にも使用方法をまとめています。併せて参考にしてみてください。
【Python】正規表現の具体的な使用例【日付、電話番号、メールアドレス、URL】
【Python】正規表現の特殊シーケンスについて【バックスラッシュ、円マーク】
【Python】reモジュールのcompile関数の使い方
【Python】正規表現の貪欲・非貪欲マッチ
スポンサーリンク