メインコンテンツへスキップ
  1. ノート/
  2. 正規表現/

正規表現の練習問題

·1774 文字·4 分· loading · loading · · ·
ICE345
著者
ICE345
CS Student | System | Linux | OCaml

正規表現を実際の処理へ使うための練習問題です。各問題では、まずパターンを自分で考えてからコードを実行し、入力例を変更して結果を確認してください。

練習1:基本的な文字列マッチング
#

目標
#

  • 123-456-7890または10桁の数字として書かれた電話番号を取り出す。
  • testで始まる単語を取り出す。
import re

text = """
連絡先A: 123-456-7890
連絡先B: 9876543210
テストデータ: test1, test2, testing
"""

phone_pattern = r'\d{3}-\d{3}-\d{4}|\d{10}'
phones = re.findall(phone_pattern, text)
print("電話番号:", phones)

test_pattern = r'\btest\w*\b'
test_words = re.findall(test_pattern, text)
print("testで始まる単語:", test_words)

練習2:ファイル名の一括変更
#

目標
#

指定したディレクトリ内からtest_で始まるファイルを見つけ、接頭辞を削除して名前を変更します。

import os
import re

folder_path = r'/path/to/folder'
pattern = re.compile(r'^test_(.+)$')

for root, dirs, files in os.walk(folder_path):
    for filename in files:
        match = pattern.match(filename)
        if not match:
            continue

        new_name = match.group(1)
        old_path = os.path.join(root, filename)
        new_path = os.path.join(root, new_name)
        os.rename(old_path, new_path)
        print(f"変更: {filename} -> {new_name}")

実際に名前を変更する前に、print(old_path, new_path)だけにして対象を確認すると安全です。同名ファイルがすでにある場合の扱いも、事前に決めておきます。

練習3:HTMLタグと空白の除去
#

目標
#

  • HTMLタグを取り除く。
  • 連続する空白文字を1つの半角スペースへ置き換える。
import re

text = """
<html>
  <body>
    <h1>テストページ</h1>
    <p>これは段落です。</p>
    <p>   余分な空白があります。   </p>
  </body>
</html>
"""

without_tags = re.sub(r'<[^>]+>', '', text)
clean_text = re.sub(r'\s+', ' ', without_tags).strip()
print(clean_text)

HTMLを本格的に解析する場合、正規表現ではなくHTMLパーサーを使ってください。ここでは単純な練習としてタグを除去しています。

練習4:メールアドレスとURLの形式確認
#

目標
#

入力が簡単なメールアドレスまたはURLの形式に合うか確認します。

import re

email = input("メールアドレスを入力してください: ")
email_pattern = r'^[A-Za-z0-9_.+-]+@[A-Za-z0-9-]+\.[A-Za-z0-9.-]+$'
print(bool(re.fullmatch(email_pattern, email)))

url = input("URLを入力してください: ")
url_pattern = r'^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,}(/.*)?$'
print(bool(re.fullmatch(url_pattern, url)))

実際のメールアドレスやURLの仕様はこのパターンより複雑です。ユーザー入力を厳密に検証する場合は、専用ライブラリやフレームワークのバリデーターを使います。

練習5:ログからIPv4アドレスを抽出する
#

import re

log_data = """
192.168.0.1 - - [24/Nov/2024:14:15:22] "GET /index.html HTTP/1.1" 200
10.0.0.5 - - [24/Nov/2024:14:16:00] "POST /form.html HTTP/1.1" 404
Invalid log entry 123.456.789.0
"""

octet = r'(?:25[0-5]|2[0-4]\d|[01]?\d\d?)'
ip_pattern = rf'(?<![\d.])(?:{octet}\.){{3}}{octet}(?![\d.])'
ips = re.findall(ip_pattern, log_data)
print("IPv4アドレス:", ips)

IPv4の各オクテットを0から255に制限するため、単に\d{1,3}と書くより長いパターンになります。

練習6:複雑なファイル名を変換する
#

次の形式のファイル名を考えます。

コース1_章2_説明_1700000000.txt

コース番号と章番号を取り出し、コース1-章2.txtへ変換します。

import os
import re

folder_path = r'/path/to/folder'
pattern = re.compile(r'^(コース\d+)_(章\d+)_.+?_(\d+)\.(.+)$')

for root, dirs, files in os.walk(folder_path):
    for filename in files:
        match = pattern.match(filename)
        if not match:
            continue

        course, chapter, _, extension = match.groups()
        new_name = f'{course}-{chapter}.{extension}'
        os.rename(os.path.join(root, filename), os.path.join(root, new_name))
        print(f"変更: {filename} -> {new_name}")

練習7:ユーザー入力からパターンを作る
#

ユーザーが入力したキーワードのいずれかを含む文を探します。入力をそのまま正規表現へ連結すると、+[などが特別な意味を持つため、re.escape()でエスケープします。

import re

text = """
今日は正規表現を勉強しました。
Pythonのプログラミングは便利です。
人工知能についても学びたいです。
"""

keywords = input("キーワードを空白区切りで入力してください: ").split()
keyword_pattern = '|'.join(map(re.escape, keywords))

if keyword_pattern:
    sentence_pattern = rf'[^。!?]*?(?:{keyword_pattern})[^。!?]*[。!?]'
    sentences = re.findall(sentence_pattern, text, re.IGNORECASE)
    print("マッチした文:", sentences)

発展させるポイント
#

  • 大文字・小文字を区別するかをre.IGNORECASEで切り替える。
  • 行単位の処理ではre.MULTILINEを試す。
  • ログ解析では、名前付きキャプチャグループを使って日付やステータスを取り出す。
  • ファイルを変更するコードは、最初に対象だけを表示してから実行する。
  • 複雑なHTML、JSON、プログラミング言語の構文は、専用パーサーを優先する。

まとめ
#

これらの練習を通じて、正規表現のマッチング、置換、キャプチャ、ファイル操作、入力検証への応用を確認できます。パターンを少しずつ変更し、境界値や不正な入力も試すと、実際の処理で使える理解が身につきます。

関連記事


评论