Python
標準ライブラリ
正規表現 - re
基本

Python 正規表現 (re モジュール): match, search, sub, findall, replace, examples

この投稿は、Pythonの正規表現モジュールであるreモジュールについてわかりやすく説明したものです。 最良のチュートリアルは常に Python の公式ドキュメントです。 この記事から始めて、公式ドキュメントを読んで、何が起こっているのかを感じてください。さっそく始めましょう!

1. 正規表現とは?

正規表現は一般的にRegex、韓国語ではreと呼ばれ、記号の集合を使って検索パターンを定義する方法です。 正規表現を使うと、テキストパターンを非常に柔軟かつ迅速に操作したり検索したりすることができます。

Pythonの組み込みモジュールである re は、正規表現を扱うための強力で効率的な方法を提供します。 ビルトインモジュールなのでインストールする必要はなく、以下のように import することで使用することができます。

import re

2. 正規表現記号のリスト

Python の正規表現は r"[regex_pattern] という形式で、生の文字列を指定します。 例えば、"python" で始まる文字列をすべて見つけるには、正規表現パターン r"^python" を使います。

正規表現パターンを定義するために使用する基本的な正規表現記号を示します。 覚えやすいようにいくつかのカテゴリーに分けました。

  • .:任意の文字(改行を除く)を意味します。

2.1.文字列の先頭と末尾(境界アンカー)

  • ^: 文字列の先頭を表す。
  • $: は文字列の終わりを表す。

2.2. 文字列のカウント(量記号)

  • ?:先行する文字がない、または1つであることを示す。
  • *: 先行する文字がない、または1文字以上先行する。
  • +: 先行する文字が1つ以上あることを意味する。
  • {n}:先行する文字がちょうどn回出現することを意味する。
  • {n,}:先行する文字がn回以上あることを意味する。
  • {n,m}: 先行する文字が n 回から m 回出現することを意味する。

2.3. 文字列フォーマット(文字クラスと文字セット)

  • \d: すべての数字を意味する。
  • \D: 数字以外の全ての文字を意味する。
  • \S: space, ˶t, ˶n, ˶r, ˶f, ˶v によって作られるすべての空白を意味する。
  • \S: 空白なしを意味する。
  • \w:すべてのアルファベットと数字、_を意味する。
  • \W: W`:全てのアルファベット、数字、_以外の全ての文字を意味する。
  • .: n 以外のすべての文字を意味する。
  • []: 角括弧で囲まれたすべての文字を意味する。

2.4. 論理演算子

  • (abc): これはグループ演算子であり、中括弧で囲まれた文字のグループがそのまま現れる。
  • [abc]: 集合演算子で、中括弧で囲まれた文字以外のすべての文字が表示される。
  • (A|B): AかBのどちらかが表示されることを意味する。

re モジュール関数の基本

Pythonの re モジュールは正規表現を扱うための関数をたくさん提供しています。よく使われる関数を以下に示します。

関数の使用パターンはセクション4の例で説明します。

  • re.match(): 文字列の先頭にある正規表現パターンがマッチするかどうかを調べる。
import re
 
pattern = r"Hello"
text = "Hello, World!"
 
match = re.match(pattern, text)
if match:
    print("Match found!")
else:
    print("No match found.")
 
# Output: Match found!
  • re.search(): 文字列全体が正規表現パターンにマッチするかをチェックする。
import re
 
pattern = r"World"
text = "Hello, World!"
 
search = re.search(pattern, text)
if search:
    print("Match found!")
else:
    print("No match found.")
 
# Output: Match found!
  • re.findall(): 文字列中の重複しないすべての正規表現パターンを文字列のリストとして返します。
import re
 
pattern = r"\d+"
text = "I have 3 apples and 5 oranges."
 
matches = re.findall(pattern, text)
print(matches)
 
# Output: ['3', '5']
  • re.finditer(): 文字列中の重複しないすべての正規表現パターンにマッチするイテレータを返します。
import re
 
pattern = r"\d+"
text = "I have 3 apples and 5 oranges."
 
matches_iter = re.finditer(pattern, text)
for match in matches_iter:
    print(match.group(), end=" ")
 
# Output: 3 5
  • re.sub(): 文字列中の正規表現パターンのすべての出現回数を、指定した置換文字列で置き換えます。
import re
 
pattern = r"apple"
text = "I have an apple. It is a delicious apple."
 
new_text = re.sub(pattern, "orange", text)
print(new_text)
 
# Output: I have an orange. It is a delicious orange.
  • re.split(): 正規表現パターンの出現回数に基づいて文字列を分割する。
import re
 
pattern = r"\s+"
text = "Hello   World!   How are you?"
 
substrings = re.split(pattern, text)
print(substrings)
 
# Output: ['Hello', 'World!', 'How', 'are', 'you?']

re モジュール関数の例

reモジュールの関数は使い慣れたので、実際の使用例を見てみましょう:

例 1: 例1: テキストから全てのメールアドレスを検索する

複数のメールアドレスを含むテキストがあり、それらをすべて抽出したいとします。 re.findall()関数を使う方法を示します:

import re
 
text = "Contact us at info@example.com or support@example.org for any inquiries."
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
emails = re.findall(email_pattern, text)
 
print(emails)  # Output: ['info@example.com', 'support@example.org']

例2: テキスト中のURLを置換文字列で置き換える

複数のURLを含むテキストがあり、それらを [URL] のような置換文字列で置換したいとします。 このタスクには re.sub() 関数を使うことができます:

import re
 
text = "Visit our website at https://example.com and check our blog at https://blog.example.com."
url_pattern = r"https?://[^\s]+"
replaced_text = re.sub(url_pattern, "[URL]", text)
 
print(replaced_text)  # Output: Visit our website at [URL] and check our blog at [URL].

例3: 異なるフォーマットから電話番号を抽出する

re.finditer()関数を使って異なるテキストフォーマットから電話番号を抽出してみましょう。

import re
 
text = "Call John at (123) 456-7890 or reach Jane at 987-654-3210 for more information."
phone_pattern = r"\(?\d{3}\)?[-\s]?\d{3}[-\s]?\d{4}"
phone_numbers = [match.group() for match in re.finditer(phone_pattern, text)]
 
print(phone_numbers)  # Output: ['(123) 456-7890', '987-654-3210']

例4:パスワードの検証

この例では、ユーザが入力したパスワードが以下の条件を満たすかどうかをチェックします: 少なくとも1つの大文字、少なくとも1つの小文字、少なくとも1つの数字、そして少なくとも合計8文字。 このタスクには re.search() を使用します。

import re
 
def is_valid_password(password):
    if len(password) < 8:
        return False
    if not re.search(r"[A-Z]", password):
        return False
    if not re.search(r"[a-z]", password):
        return False
    if not re.search(r"\d", password):
        return False
    return True
 
password = "P4ssw0rd!"
print(is_valid_password(password))  # Output: True

例5: 複数の記号に基づく文字列の分割

この例では、re.split()関数を使用して、複数の区切り記号(カンマ、セミコロン、パイプ)に基づいて文字列を分割します:

import re
 
text = "apple,banana;orange|grape"
delimiter_pattern = r"[,;|]"
fruits = re.split(delimiter_pattern, text)
 
print(fruits)  # Output: ['apple', 'banana', 'orange', 'grape']

5. さらに踏み込む

基本的な正規表現の構文や関数のほかにも、正規表現を使う価値があるトピックがあります。

  • 先読みアサーションと後追いアサーション: 与えられた正規表現パターンに対して、さらにパターンを登録する方法。
  • 名前付きセットと後方参照: 正規表現で階層や変数に似たテクニックを使う方法。
  • 非捕捉グループ: グループを使用してパターンを検索するが、その値は無視するテクニック。

その他、大文字小文字を区別しない検索、複数行モードなど、便利なテクニックを学ぶことができる。

6. reモジュールを使うためのヒント

正規表現を使いやすくするためのヒントをいくつか紹介します:

  • バックスラッシュをエスケープする必要がないように、正規表現パターンに生の文字列 (r"") を使ってください。 Pythonの正規表現でバックスラッシュを使うとエスケープする必要がありますが、生の文字列を使えばその必要はありません。
  • Regex101は正規表現パターンのテストやデバッグに便利なオンラインツールです。一度コツをつかめば、いつも使うことになるでしょう。
  • 複雑な正規表現パターンを作るのは読みにくく、管理しにくいものです。小さく管理しやすい単位に分割することで、より読みやすく保守しやすいものになります。
  • 正規表現パターンを理解しやすくするには、コメントと冗長モード(re.VERBOSE)を使います。 re.compile()と併用することで、冗長なコメントを追加することができます。

7. 最後に

正規表現はPythonでテキスト操作やパターンマッチを行うための強力なツールです。 reモジュールに慣れ、正規表現の基本的な構文を理解することで、様々なテキストタスクを簡単に処理できるようになります。

copyright for Python re basics

© 2023 All rights reserved.