Pythonで文字列処理を行う際、正規表現は欠かすことのできない非常に強力なツールです。
しかし、デフォルトの正規表現エンジンは大文字と小文字を厳密に区別して動作します。
例えば「Python」という単語を検索する場合、小文字の「python」や大文字の「PYTHON」にはマッチしません。
このようなケースで役立つのが、正規表現のフラグとして用意されているre.IGNORECASEです。
本記事では、Pythonの正規表現モジュールであるreを使用して、大文字・小文字を無視してマッチングを行う方法を詳しく解説します。
正規表現で大文字・小文字を無視する基本:re.IGNORECASE
Pythonの正規表現で大文字・小文字を区別しないようにするには、reモジュールの関数にre.IGNORECASEフラグを指定するのが最も標準的な方法です。
このフラグを指定することで、正規表現エンジンは「A」と「a」を同一の文字として扱います。
なお、re.IGNORECASEは非常に頻繁に使用されるため、省略形であるre.I(大文字のアイ)も用意されています。
まずは、基本的なre.search()関数での動作を確認してみましょう。
import re
text = "Learning Python is fun!"
pattern = r"python"
# フラグなしの場合(マッチしない)
match_no_flag = re.search(pattern, text)
print(f"フラグなし: {match_no_flag}")
# re.IGNORECASEを使用した場合(マッチする)
match_with_flag = re.search(pattern, text, re.IGNORECASE)
print(f"re.IGNORECASEあり: {match_with_flag.group()}")
フラグなし: None
re.IGNORECASEあり: Python
このように、フラグを指定するだけで検索の柔軟性が大幅に向上することがわかります。
主要な関数でのre.IGNORECASEの使い方
reモジュールにはさまざまな用途に応じた関数が用意されていますが、その多くで第3引数以降にフラグを渡すことができます。
ここでは、代表的な関数における記述方法を紹介します。
re.findall() での一致箇所すべての取得
文章内にある特定キーワードをすべて抽出したい場合には、re.findall()を使用します。
この際、re.IGNORECASEを指定すると、表記の揺れを気にせずすべて取得可能です。
import re
text = "Python, python, and PYTHON are all the same."
result = re.findall(r"python", text, re.IGNORECASE)
print(result)
['Python', 'python', 'PYTHON']
re.sub() での置換処理
文字列の置換を行うre.sub()でも、大文字・小文字を無視した置換が可能です。
置換対象の表記が混在している場合に非常に有効なテクニックです。
import re
text = "The user input was Python, but the log says python."
# 大文字小文字を無視して「Python」を「JavaScript」に置換
replaced = re.sub(r"python", "JavaScript", text, flags=re.IGNORECASE)
print(replaced)
The user input was JavaScript, but the log says JavaScript.
re.sub()の場合、引数の順番に注意が必要です。
第4引数にcount(置換回数)があるため、フラグを指定する際はflags=re.IGNORECASEのようにキーワード引数で指定することを強く推奨します。
re.split() での分割処理
特定の文字列で文章を分割したいときも同様です。
例えば、大文字小文字が混ざった「SEP」という文字列で分割したい場合は以下のように記述します。
import re
text = "Item1SEPItem2sepItem3SepItem4"
parts = re.split(r"sep", text, flags=re.IGNORECASE)
print(parts)
['Item1', 'Item2', 'Item3', 'Item4']
正規表現パターン内にインラインフラグを埋め込む方法
関数の引数としてフラグを渡すのではなく、正規表現のパターン文字列の中に直接フラグを埋め込む手法もあります。
これを「インラインフラグ」と呼び、(?i)という記法をパターンの先頭に記述します。
import re
text = "Hello WORLD"
# パターンの先頭に (?i) を入れる
match = re.search(r"(?i)world", text)
if match:
print(f"マッチしました: {match.group()}")
マッチしました: WORLD
この方法の利点は、re.compile()などでコンパイルされたパターンを使い回す際や、フラグ引数を受け取らないライブラリ経由で正規表現を渡す際に便利である点です。
また、パターンの特定の部分だけを無視したい場合には、(?i:...)というグループ化の構文を使うこともできます(ただし、Pythonの標準reモジュールのバージョンによっては動作が異なるため、基本的には全体適用として使われることが多いです)。
re.compile() によるパフォーマンスの最適化
同じ正規表現パターンを何度も繰り返し使用する場合、re.compile()を使ってパターンを事前にオブジェクト化しておくのが一般的です。
この場合、コンパイル時に re.IGNORECASE を指定します。
import re
# パターンのコンパイル(ここでフラグを指定)
pattern_obj = re.compile(r"apple", re.IGNORECASE)
words = ["Apple", "APPLE", "banana", "aPpLe"]
# コンパイル済みオブジェクトを使用して検索
for word in words:
if pattern_obj.search(word):
print(f"Found match: {word}")
Found match: Apple
Found match: APPLE
Found match: aPpLe
コンパイル時にフラグを設定しておくことで、その後のsearchやmatchの呼び出し時に毎回フラグを指定する必要がなくなります。
大量のテキストデータに対して繰り返し処理を行う際は、この方法が実行速度の向上に寄与します。
複数のフラグを同時に使用する方法
実務では、大文字・小文字の無視に加えて、他のフラグを併用したい場面が多々あります。
例えば、ドット(.)を改行にもマッチさせるre.DOTALLや、複数行にまたがる検索を行うre.MULTILINEなどです。
複数のフラグを指定するには、ビット演算子の「|」(パイプ)を使用します。
import re
text = """First line
second line"""
# 大文字小文字無視 + 複数行モード
pattern = re.compile(r"^SECOND", re.IGNORECASE | re.MULTILINE)
match = pattern.search(text)
if match:
print(f"見つかりました: {match.group()}")
見つかりました: second
このようにフラグを組み合わせることで、複雑な条件でのテキスト抽出をシンプルに記述できます。
正規表現と文字列メソッドの使い分け
大文字・小文字を無視してマッチングを行いたい場合、必ずしも正規表現を使う必要はありません。
単純な文字列比較であれば、Pythonの標準文字列メソッドであるlower()やupper()、またはcasefold()を使用した方が高速で読みやすい場合があります。
| 手法 | メリット | デメリット |
|---|---|---|
str.lower() | 高速、シンプルで読みやすい。 | 単純な比較しかできず、複雑なパターンには不向き。 |
re.IGNORECASE | 柔軟なパターンマッチが可能。 | 文字列メソッドに比べると処理が重い。 |
str.casefold() | 多言語(Unicode)の比較に強い。 | 正規表現のような高度な検索は不可。 |
特定の単語が含まれているかを確認するだけであれば、以下の書き方で十分です。
text = "Python Programming"
if "python" in text.lower():
print("含まれています")
しかし、「数字と組み合わさった特定の単語」や「文頭にある特定のパターン」などを探す場合は、正規表現のre.IGNORECASEが唯一の選択肢となります。
よくある質問と注意点
日本語(全角文字)の大文字・小文字にも有効ですか?
re.IGNORECASEは主にアルファベットの「A-Z」と「a-z」に対して機能します。
日本語の全角アルファベット(Aとa)についても、Python 3の正規表現エンジンはUnicodeを標準でサポートしているため、基本的には正しく機能します。
ただし、カタカナの「ア」と「ァ」のような清音と拗音を同一視する機能はありませんので注意してください。
re.match() と re.search() の違いは何ですか?
これは正規表現全般の注意点ですが、re.match()は「文字列の先頭」がパターンに一致するかを判定します。
一方で、re.search()は「文字列のどこか」に一致するかを判定します。
大文字小文字を無視したい場合でも、この挙動の違いを理解していないと「マッチするはずなのにマッチしない」というトラブルに陥りやすくなります。
まとめ
Pythonで大文字・小文字を無視して正規表現マッチングを行うには、re.IGNORECASEフラグを活用するのが最も効率的です。
関数の引数として渡す方法、re.compile()で事前に設定する方法、そして(?i)を使用してパターン内に記述する方法の3種類を状況に応じて使い分けましょう。
また、複雑なパターンが必要ない場合は、lower()メソッドによる比較も検討することで、コードの可読性とパフォーマンスを両立させることができます。
正規表現のフラグを正しく使いこなし、柔軟性の高いテキスト処理を実現してください。
