正規表現難しいですか?基本を理解
- 2025年07月23日
- CATEGORY- 1. 技術力{技術情報}167
プログラミングやデータ処理において欠かせないツールの一つに「正規表現(Regular Expressions)」があります。でも、「正規表現は難しい」「暗号なんだけど」「いまさら覚える必要ある?」と感じる方も多いのではないでしょうか。実際には実務で使えると非常に強力なツールです。
正規表現の基本をわかりやすく解説し、その難しさを乗り越えるためのポイントを紹介します。
目次
正規表現とは
正規表現は、文字列のパターンを定義するための言語です。主に文字列の検索、置換、検証に使用される事になります。
例えば、メールアドレスや電話番号の形式をチェックしたり、特定の単語を抜き出したりする際に利用されるんですが、これ正規表現使わず、pythonなどの言語を使って例えばメールアドレスはおろか、電話番号が書式に合ってるかどうかすら、実は結構煩雑な処理になります。ちょっとpythonで書いてみましょうか。
_samples_ok = [
"03-1234-5678","045-123-4567","090-1234-5678",
"0120-123-456","0312345678","0451234567",
"+81-3-1234-5678","+81-90-1234-5678",
"+81312345678","+819012345678",
"08012345678","080-1234-5678",
"0570-123-456","0120123456",
]
_samples_ng = [
"03-1234-567","+1-202-555-0199","090-12345678-",
"++819012345678","(03)1234-5678","abc",
"03 1234 5678"," 090-1234-5678 ","03-1234-5678",
"+81 3-1234-5678","+81-3-1234-5678-",
"03-123-45678","008012345678","090-1234-5678ext123",
"03-1234-56789","+8190123456789","+81-090-1234-5678",
]
上記が、OKパターン、NGパターンです。これをもとに、NGパターンをはじいて、 OKパターンだけを通すような処理を書いてみましょう。
まず、正規表現を使わずに出来るだけ簡単に書いてみます。
def is_valid_phone(s):
# Reject boundary or consecutive hyphens
if s.startswith('-') or s.endswith('-') or '--' in s:
return False
# Hyphenated formats
if '-' in s:
parts = s.split('-')
# International with hyphens: +81-A-B-C, A must not start with '0'
if parts[0] == '+81':
if len(parts) != 4:
return False
a, b, c = parts[1], parts[2], parts[3]
if a.startswith('0'):
return False
return (a.isdigit() and b.isdigit() and c.isdigit()
and 1 <= len(a) <= 4
and 1 <= len(b) <= 4
and len(c) == 4)
# Domestic with hyphens
if parts[0].startswith('0'):
if len(parts) != 3:
return False
a, b, c = parts
# Free-dial patterns 0120, 0570, 0800: group sizes 4-3-3
if a in ('0120', '0570', '0800'):
return (b.isdigit() and c.isdigit()
and len(b) == 3 and len(c) == 3)
# Standard: A(2-5)-B(1-4)-C(4)
return (a.isdigit() and b.isdigit() and c.isdigit()
and 2 <= len(a) <= 5
and 1 <= len(b) <= 4
and len(c) == 4)
return False
# Non-hyphen formats
if s.startswith('+81'):
d = s[3:]
return (d.isdigit() and 9 <= len(d) <= 10
and not d.startswith('0'))
if s.startswith('0'):
return s.isdigit() and len(s) in (10, 11)
return False
どうですかね。わかりやすいですか?これ、電話番号のチェックです。メールアドレスになるとこんなもんじゃすみません。次に正規表現を使ったバージョンがどうなるか見てみましょう。
import re
_pattern = re.compile(
r'^(?:'
r'(?:0120|0570|0800)-\d{3}-\d{3}' # フリーダイヤル/サービス番号
r'|0\d{1,4}-\d{1,4}-\d{4}' # 国内ハイフン付き
r'|0\d{9,10}' # 国内ハイフンなし
r'|\+81-[1-9]\d{0,3}-\d{1,4}-\d{4}' # 国際ハイフン付き(先頭数字0禁止)
r'|\+81[1-9]\d{8,9}' # 国際ハイフンなし(先頭数字0禁止)
r')$'
)
def is_valid_phone(s):
return bool(_pattern.match(s))
どうでしょう?どっちがわかりやすいでしょうか?わかりやすいわかりにくいというか、 正規表現使わないともはや解読不可能ではないでしょうか? 「普通にpython版も解読できるよ」っていう人は読解力スゴイですが。
正規表現を使うことで、複雑な文字列操作を効率的に行うことが可能、と言葉で言うより コードで見たらわかりやすいのではないでしょうか。
正規表現の基本構文
さて、「正規表現めっちゃ大事やんけ」と思っていただいたところで、正規表現の基本を説明してみたいと思います。
正規表現では、文字や記号を組み合わせてパターンを作成します。以下に、基本的な構文を紹介します。
リテラル文字
リテラル文字は、そのままの文字としてマッチします。例えば、正規表現「cat」は「cat」という文字列にマッチします。
メタ文字
メタ文字は、特別な意味を持つ文字で、パターンの柔軟性を高めます。代表的なメタ文字には以下のものがあります。
.- 任意の一文字にマッチ*- 直前の文字の0回以上の繰り返しにマッチ+- 直前の文字の1回以上の繰り返しにマッチ?- 直前の文字の0回または1回の繰り返しにマッチ[]- 文字クラス。指定したいずれかの文字にマッチ()- グループ化。部分パターンをグループとして扱う|- OR演算子。いずれかのパターンにマッチ^- 行の先頭にマッチ$- 行の末尾にマッチ
よく使うメタ文字
以下に、正規表現でよく使用されるメタ文字とその意味をまとめます。
| メタ文字 | 意味 |
|---|---|
. |
任意の一文字にマッチ |
* |
直前の文字の0回以上の繰り返しにマッチ |
+ |
直前の文字の1回以上の繰り返しにマッチ |
? |
直前の文字の0回または1回の繰り返しにマッチ |
[] |
文字クラス。指定したいずれかの文字にマッチ |
() |
グループ化。部分パターンをグループとして扱う |
| |
OR演算子。いずれかのパターンにマッチ |
^ |
行の先頭にマッチ |
$ |
行の末尾にマッチ |
\d |
任意の数字にマッチ |
\w |
任意の単語文字(英数字とアンダースコア)にマッチ |
\s |
任意の空白文字にマッチ |
正規表現の実例
正規表現を具体的な例で理解しましょう。以下に、いくつかの実例を紹介します。
メールアドレスの検証
/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/
この正規表現は、一般的なメールアドレスの形式を検証します。行の先頭( ^ )から始まり、ユーザー名部分、@マーク、ドメイン名部分、ドットとトップレベルドメイン($)で終わるパターンにマッチします。
電話番号の抽出
/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/
この正規表現は、ハイフンやドットがあるかないかに関わらず、10桁の電話番号にマッチします。単語境界(\b)で囲まれた3桁、3桁、4桁の数字のパターンです。
電話番号の検証の例でも正規表現を使いましたが、メールアドレスも電話番号も実際にはもっと細かい規則があり、これだけじゃほんとは足りません。上記はあくまで簡略化したサンプルです。
URLの抽出
/https?:\/\/(?:www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(?:\/\S*)?/
URLもやってみましょう。こんな感じ。なんとなーくわかりますかね?
この正規表現は、httpまたはhttpsで始まるURLにマッチします。オプションでwww.が含まれ、ドメイン名とトップレベルドメインの後に任意のパスが続くパターンです。
正規表現を学ぶためのヒント
正規表現は一見難しく感じられるかもしれませんが、以下のヒントを参考に学習を進めることで、基本を理解しやすくなります。
- 小さなパターンから始める: 簡単なパターンを作成し、少しずつ複雑なパターンに挑戦していく。
- オンラインツールを活用する: Regex101などのオンライン正規表現テスターを使用して、リアルタイムでパターンの動作を確認する。これはもう必須と思ってください。絶対使った方がいいです。
- リファレンスを参照する: 正規表現のリファレンスガイドやチートシートを手元に置き、必要な時に参照する。
- 実践的な問題を解く: 実際のプロジェクトや課題で正規表現を使用し、実践を通じて理解を深める。
- 逃げられない事を理解する:正規表現からは逃げられません
継続的に練習することで、正規表現の理解が深まり、自然と使いこなせるようになります。
まとめ
正規表現は、初めて学ぶ際には難しく感じるかもしれませんが、活用できるようになるとめっちゃ強力で、仕事力がアップします。書き捨てのスクリプトでは特に威力を発揮します。
コーディングでのテキスト処理もそうなのですが、データ検証やログ調査が格段に、というか1000倍、一万倍のレベルで効率的になります。
正規表現をマスターすることで、日常の作業がよりスムーズになり、生産性の向上につながります。ぜひこの記事をきっかけに、正規表現になじんでいってください。
- 2025年07月23日
- CATEGORY- 1. 技術力{技術情報}167

