lisz-works

技術と興味の集合体

python3 正規表現検索と注意点

【スポンサーリンク】

Python

検索や置換の強力なオトモといえば、正規表現。

今回はPythonで、正規表現を使った検索についてです!

import

Pythonで正規表現を使うには、コチラをimportします。

import re

正規表現でマッチ箇所を検索

関数 効果
match(pattern, str) 先頭から比較してマッチするか?
search(pattern, str) 先頭から検索して行ってマッチするものがあるか?

例えば、この文字列が検索対象とします。

>>> target = 'xxxx0000yyyy1111'

コレに対してmatch/searchを試してみましょう。

>>> re.match(r'[a-z]{4}', target)
<_sre.SRE_Match object; span=(0, 4), match='xxxx'>
>>> re.search(r'[a-z]{4}', target)
<_sre.SRE_Match object; span=(0, 4), match='xxxx'>
>>>
>>> re.match(r'[0-9]{4}', target)
>>> re.search(r'[0-9]{4}', target)
<_sre.SRE_Match object; span=(4, 8), match='0000'>

'[a-z]{4}'の場合、どちらもマッチしたので、結果が返ってきています。

どちらも「最初にヒットしたパターン」が結果として返ってきます。

'[0-9]{4}'の場合、matchは「先頭から比較してマッチするか?」をチェックするので、「マッチしていない」状態となってます。
マッチしていない場合、Noneが返ってきます。

だからmatchでは結果が何も表示されていませんね。

正規表現で全てのマッチ箇所を取得

「マッチした全てのパターンを取得したい!」

という場合は、「findall」を使用します。

こんな感じ。

>>> target = 'xxxx0000yyyy1111'
>>> re.findall('[a-z]{4}', target)
['xxxx', 'yyyy']

リストで返ってくるので、取り扱いもラクラクですね!

>>> res = re.findall('[a-z]{4}', target)
>>> for s in res:
...    print(s)
...
xxxx
yyyy

()を使うとうまくヒットしないケース

findallを試していて、うまくヒットしないケースに遭遇しました。

例えばこんな文字列を検索するとします。

>>> target = 'x0x0x0x0,x0x0x0x0,x0x0x0x0,x0x0x0x0'

このとき、「','以外のものをマッチするようにして、リストとして取得したい」とします。
こういうのが欲しいわけです。

['x0x0x0x0', 'x0x0x0x0', 'x0x0x0x0', 'x0x0x0x0']

ということでfindallを使っていきます。

例えばこのようにすると、望みどおりのものを取得することができました。

>>> re.findall(r'[a-z][0-9][a-z][0-9][a-z][0-9][a-z][0-9]', target)
['x0x0x0x0', 'x0x0x0x0', 'x0x0x0x0', 'x0x0x0x0']

しかしちょっとクドいですよね。

ということで、「繰り返し」を使ってを短縮しよう!

と思ったその時……

>>> re.findall(r'([a-z][0-9]){4}', target)
['x0', 'x0', 'x0', 'x0']

なぜかマッチはしてる扱いだが、繰り返し部分が取られていない……

正規表現をチェックするサイトで見ても、特に問題がなさそう……

Debuggex結果

https://www.debuggex.com

Regular Expression Test Drive 結果

Regex Test Drive | 正規表現オンラインテストサイト

バグ……?

参考

コチラを参考にしました。ありがとうございました!

Pythonでの正規表現の使い方 - Qiita

正規表現 HOWTO — Python 3.6.5 ドキュメント

あとがき

ということで、Pythonによる正規表現での検索についてでした!

matchで「先頭一致」を使う以外は、基本的にfindallでいいんじゃないかなーと思っています。

ただ、今回のように「なぜかうまく取得できないケース」などがある可能性があるので、適宜注意が必要かもしれません。