私は正規表現純粋主義者をひるませる告白を持っています。私のキャリアの最初の数年間、私はスタック オーバーフローからコピーペーストし、1 文字を変更し、コードを実行し、失敗するのを見て、たまたま機能するまで繰り返すことで正規表現を書きました。私はそうしました'パターンを理解していません - 私はそれらを服従させていました。それは遅かったし、さらに悪いことに、私が出荷したパターンは私ができなかった方法で壊れやすかったです'見ていません。
What fixed that was't reading the theory (最終的には読んだけど) それはビジュアルテスター - パターンをタイプするボックス、テスト文字列を貼り付けるボックス、そして何かを変更した瞬間に光るマッチング - 突然できた みるの なんでや \d+ 私が望んでいた以上に、またはメール パターンが完全に有効なアドレスを拒否した理由。 正規表現は推測ゲームではなくなり、フィードバック ループがきつくなってしまいました。
それはまさに 正規表現ビルダー on Toolz.dev is. you write a pattern, drop in test data, toggle flags, and watch the matches and captured groups highlight in real time.これは完全にブラウザで実行されるため、ログ行またはユーザーデータ you're testing againstはどこにもアップロードされません。このガイドは、私が当時I'dに持っていたらよかったと思う正規表現です。実際に再利用したパターン、完全なチートシート、そして実稼働サーバーを破壊する可能性のある唯一の間違いです。
tl;dr: パターンとテスト文字列を 正規表現ビルダー そして、
g/i/m試合をライブで見るフラグ。 簡単に始めて、誤検知を殺すために制約を追加し、敵対的な入力をテストして、壊滅的なバックトラッキングを回避します。 抽出されたデータの場合は、 JSON フォーマッタ あんど Base64 コンバーター。 すべてのクライアント側、すべて無料。
正規表現とは正確には何ですか?
正規表現 - regex または regexp - は、検索パターンを記述するコンパクトな文字列です。 " の代わりに cat," という単語を見つけます " 任意の 5 桁の数値を見つけます " " メールのように見えるものを見つけます " または " ERROR で始まるすべての行を見つけます " ほぼすべての言語とエディターがそれらをサポートしているため、スキルは非常にポータブルです。一度学習すると、JavaScript、Python で使用できます grep、そしてあなたの IDE は検索と置換をします。
この概念は 1950 年代の正式な言語理論から生まれ、ケン トンプソンは 1960 年代にテキスト編集のためにそれをコンピューティングに配線しました。 歴史が重要な理由として、「通常の」言語には制限があります。そのため、正規表現では、どんなに賢くても HTML のようなネストされた構造を真に解析できないのはそのためです。
通常の 1 週間で正規表現に到達する: データベースにアクセスする前にユーザー入力を検証し、非構造化ログ ラインからフィールドを引き出し、コードベース全体で検索と置換を行い、単純な検索では表現できない、移行中にデータをフィルタリングします。 ザ・ 正規表現ビルダー 実際のコードに近いところに行く前に、それらすべてをプロトタイプ化したところです。
基本的な構成要素は次のとおりです - あなたがパターンを組み立てるアルファベット:
| 構文 | 意味 | 例 | マッチ |
|---|---|---|---|
. |
改行以外の文字 | h.t |
帽子、ホット、ヒット |
\d |
任意の数字 (0-9) | \d{3} |
123、456 |
\w |
文字 (a-z、a-z、0-9、_) | \w+ |
こんにちは、test_123 |
\s |
空白 | hello\sworld |
こんにちは |
^ |
文字列の先頭 | ^Hello |
はじめにこんにちは |
$ |
文字列の終わり | end$ |
最後に終わる |
* |
ゼロ以上 | ab*c |
AC、ABC、ABBC |
+ |
1つ以上 | ab+c |
ABC、ABBC |
? |
ゼロか1 | colou?r |
色、色 |
{n} |
正確にn回 | \d{4} |
2026 |
{n,m} |
N から M の間 | \d{2,4} |
12、123、1234 |
[abc] |
キャラクタークラス | [aeiou] |
任意の母音 |
[^abc] |
否定クラス | [^0-9] |
非数字 |
(...) |
グループをキャプチャ | (hello) |
「こんにちは」をキャプチャします。 |
a|b |
交替 (または) | cat|dog |
猫か犬か |
すべての開発者が手元に置いておくべき正規表現のパターンはどれですか?
これらは、私がテストした、壊れ、修正したもので、個人のスニペット ファイルに保存されています。 それらを直接コピーして 正規表現ビルダー そして、自分のエッジケースを投げつけてください。
メール(実用的な種類)
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
これは一致します [email protected] あんど [email protected]、および拒否します @example.com や user@com。 ただし、ここで重要な正直さがあります。完全なメール文法 RFC 5322 は、怪物的に複雑です - それは技術的に引用文字列を許可し、コメントはほとんど誰も使用していません. Don& #39; tは、regexで100% RFC準拠を追いかけます. practical 99% を上記のパターンと一致させ、次に確認メールを送信することで、アドレスが本物であることを確認します. that& #39; s the mistake I see most: teams burning days on an "airtight" email regex that still can' t tell a real inbox from a typo.
url
^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$
マッチ https://toolz.dev あんど http://www.example.com/path?query=value; 拒否します ftp://... そしてプレーンテキスト。
米国の電話番号
^(\+1)?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$
十分に柔軟 555-123-4567、 (555) 123-4567、 +1 555.123.4567、そして 5551234567。
IPv4 アドレス
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
入れ子になった代替は、各オクテットが 0 ~ 255 のままであるため、正しく拒否されるものです。 999.999.999.999。
強力なパスワード チェック
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
小文字、大文字、数字、記号を含む 8 文字以上が必要です。 ザ・ (?=...) 先読みは、文字を消費せずにそれぞれ 1 つの条件を主張します。これは理解する価値のある優れたトリックです。
ISO 日付 (YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
マッチ 2026-07-11、拒否します 2026-13-01 あんど 2026-02-32。
六角色
^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
マッチ #4466EE、 #abc、 #000000。
正規表現のチートシート
これを固定しておきます。 私が最もチェックする参考書です。
アンカー
| パターン | 説明 |
|---|---|
^ |
文字列の始まり (または複数行モードの行) |
$ |
文字列の終わり (または複数行モードの行) |
\b |
単語境界 |
\B |
非単語境界 |
数量詞
| パターン | 説明 |
|---|---|
* |
0 以上 (貪欲) |
+ |
1以上(貪欲) |
? |
0 または 1 (貪欲) |
*? +? ?? |
怠惰なバージョン - できるだけ一致しません |
{n} {n,} {n,m} |
正確に n / n 以上 / n と m の間 |
文字クラス
| パターン | 説明 |
|---|---|
[abc] |
a、b、または c |
[^abc] |
A、B、C ではありません |
[a-z] [A-Z] [0-9] |
範囲 |
\d \D |
数字/非数字 |
\w \W |
単語 char / 非単語 char |
\s \S |
空白 / 非空白 |
グループとルックアラウンド
| パターン | 説明 |
|---|---|
(abc) |
グループを捕まえている |
(?:abc) |
非捕獲グループ |
(?<name>abc) |
名前付き捕獲グループ |
(?=abc) / (?!abc) |
ポジティブ/ネガティブ ルックア |
(?<=abc) / (?<!abc) |
ポジティブ/ネガティブのルックビハインド |
フラグ
| 旗 | 説明 |
|---|---|
g |
グローバル - すべての一致を見つけます |
i |
大文字小文字を区別しない |
m |
マルチライン - ^ あんど $ ライン境界に一致 |
s |
Dotall - . 改行に一致 |
u |
Unicode サポート |
1 時間も無駄にせずに、どのようにパターンを構築してデバッグしますか?
退屈は繰り返し可能であるため、私のプロセスはわざと退屈です。
- 1 つの実際の例に一致する最も単純なものから始めます。 すべてのケースを一度に処理しようとしないでください。
- 正と負の両方のテスト文字列を貼り付けます に 正規表現ビルダーー一致すべきものと、一致してはならないもの.
- 偽陽性を殺すために締めます。 アンカーを追加する (
^、$) ということで、パターンは文字列全体に一致し、スワップします.などの特定のクラスの場合[a-z]や[^,]。 - 敵対的な入力を投げる- 空の文字列、巨大な入力、Unicode、データとしてのリテラル正字数。
- 最適化されます。
何かがうまくいかない場合、ほとんどの場合、3 つのうちの 1 つになります。 それならば マッチしすぎ、あなたの量指定子は貪欲です - 怠け者にします ()*?) またはあなたのクラスをより具体的にします。 それならば 一致が少なすぎる、おそらく必要です i フラグまたは特殊文字をエスケープするのを忘れました。 それならば まったく一致しない、エスケープされていないメタ文字をチェックします (.、 *、 +、 (、 [、 {など) 文字通りにすることを意味し、またはテスト文字列に隠れているタブのような非表示の文字を意味します。
壊滅的な後退とは何ですか。なぜそれを恐れる必要があるのでしょうか?
これは、できれば新しい開発者にタトゥーを入れるセクションです。 早い段階で、完全に無害に見える入力検証正規表現を出荷しました。ある日の午後、1 回のリクエストで 100% の CPU コアが 100% に固定され、そこにとどまりました。 パターンが問題でした。
正規表現エンジンが一致するものを見つけられない場合、 バックトラックー後退し パターンを満たす他の方法を試みます ある図形はパスの数を指数関数的に爆発させます 教科書の例:
^(a+)+$
のような入力をフィードする aaaaaaaaaaaaaaaaaaaab (一言で言うと a で終わる b)、およびネストされた量指定子は、エンジンに天文学的な数の分割方法を提供します。 as は、「一致しない」と結論付ける前に試行します。アプリがフリーズします。 これは、次のようなサービス拒否クラスです。 レド (正規表現サービスの拒否)、攻撃者はそれを悪用します。
安全を確保する方法:
- 量指定子を入れ子にしないでください。
(a+)+、(a*)*、そして(a+)*危険信号です。 - 原子群または所有量指定子を使用する エンジンがそれらをサポートする場所:
(?>a+)やa++。 - 具体的に。
[a-z]+よりも後戻りする.+探索するパスが少ないからです。 - パターンを固定する そのため、エンジンは、不一致入力で高速に故障します。
- ほぼ一致するが最後に失敗する文字列でテストする- それと#39;バックトラックにとって最悪のケースです。
移動中の場合、この問題は存在しないため、次のセクションに移動します。
正規表現は言語によってどのように異なりますか?
コア構文はうまく移動しますが、詳細はバイトです。 これらは、私が実際につまずいた違いです。
JavaScript:
const regex = /\d{3}-\d{4}/g;
const pattern = new RegExp('\\d{3}-\\d{4}', 'g'); // note the doubled backslashes
'555-1234'.match(regex); // ["555-1234"]
const m = '2026-07-11'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
m.groups.year; // "2026"
気をつけてください: ルック・ビハインドは ES2018 に到着したばかりで、 \d ASCII 桁のみに一致し、 g フラグが作る .test() ステートフル経由 lastIndex- ループ内の微妙なバグ ソース。
パイソン:
import re
pattern = re.compile(r'\d{3}-\d{4}') # raw strings avoid double-escaping
pattern.findall('Call 555-1234 or 555-5678') # ['555-1234', '555-5678']
常に生の文字列を使用します (r'...'. 覚えて re.match 開始時にアンカーのみ - 使用してください re.search どこかを見つけるために。 あんど re.VERBOSE 複雑なパターンの命の恩人である、複数行のコメント付きパターンを記述できます。
PHP: パターンが必要な区切り文字 ('/\d{3}-\d{4}/')、強力な PCRE エンジンを使用し、 preg_match 返品 1、 0、または false エラーの場合は、確認してください ===。
行く: 意図的に RE2 エンジンを使用します。 先読み、後方、後方参照を削除します 線形時間マッチングの保証と引き換えに。つまり、壊滅的なバックトラックさえ不可能であるということです。信頼できない入力マッチングの言語を選択すると、知る価値のあるまったく異なるトレードオフです。
実例: Apache ログ行の解析
これが正規表現の種類です。 標準の Apache アクセス ログの行は次のようになります。
192.168.1.1 - frank [11/Jul/2026:10:27:10 -0500] "GET /api/users HTTP/1.1" 200 1234
このパターンはそれを引き離します。
^(\S+) \S+ (\S+) \[([^\]]+)\] "(\S+) (\S+) (\S+)" (\d{3}) (\d+)$
両方に貼り付けます 正規表現ビルダー そして、キャプチャされた各グループが個別に点灯します。
| 群 | 内容 | 例 |
|---|---|---|
| 1です | IPアドレス | 192.168.1.1 |
| 2です | ユーザー名 | さすが |
| 3つです | タイムスタンプ | 11/2026:10:27:10 -0500 |
| 4です | http メソッド | ゲット |
| 5です | リクエストパス | /api/ユーザー |
| 6か | http バージョン | http/1.1 |
| 7です | ステータスコード | 200 |
| 8です | 応答サイズ | 1234 |
グループがテスターに並んだら、それを re.findall Python または match() javascript では些細なことです。そして、それが機能することはすでにご存知でしょう。
よくある質問
正規表現ビルダーとは何ですか?
正規表現ビルダーは、正規表現を入力すると、テスト文字列と一致して一致し、一致およびキャプチャされたグループが強調表示されるインタラクティブなツールです。 これは、コード内の遅い書き込み-実行-失敗-書き換えループをライブ ループに置き換えます。 ザ・ 正規表現ビルダー on Toolz.dev では、これはすべてブラウザーで行われるため、テスト データはマシン上に残ります。
正規表現パターンはすべてのプログラミング言語で同じですか?
コアの構文はほぼ同じですが、詳細はバグの原因となるほど異なります。 古い JavaScript には後回しが欠けていました。Go の RE2 エンジンには先読みや後参照がまったくなく、Python の名前はグループに含まれています。 (?P<name>...) いくつかのコンテキストで。 移植性を想定するのではなく、実際にターゲットにしている言語でパターンを確認してください。
正規表現でメール アドレスを検証するにはどうすればよいですか?
次のような実用的なパターンを使用します。 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$、これは、実際のアドレスの大部分を処理します。 regexで完全なrfc 5322 コンプライアンスを試みないでください - 文法はあまりにも複雑すぎて、you& #39;llはまだ有効なアドレスを拒否するか、またはタイプミスを受け入れます。 regexと検証メールをペアリングして、受信トレイが実際に存在することを確認します。
正規表現がアプリケーションをフリーズするのはなぜですか?
ほとんどの場合、壊滅的な後退を繰り返します。 ネストされた数量詞のようなパターン (a+)+ ほとんど一致するが最終的に失敗する入力に遭遇したときに、一致する指数関数的なパスを作成し、エンジンはそれらすべてを試行します。 ネストされた量指定子を削除して、特定の文字クラスを優先します。 .+、そしてアンカーを追加して、エンジンがすぐに故障するようにします。
正規表現を使って HTML または JSON を解析できますか?
いいえ、些細な抽出以上のものには向いていません。 HTML と JSON は通常の言語ではありません - regex が基本的に追跡できない任意のネストを許可します。 real パーサーを使用します: HTML 用の DOMParser または Cheerio、および JSON.parse または JSON 用の JSON ツール。 正規表現は、構造がネストする瞬間のツールが間違っています。
グリーディとレイジー マッチングの違いは何ですか?
貪欲な量指定子 (*、 +、 ?) できるだけ多くを取得し、必要に応じて後戻りします。*?、 +?、 ??) はできるだけつかみ、強制的にしか展開しないでください。 に対して <b>bold</b>、貪欲 <.*> 怠惰な間、弦全体を飲み込む <.*?> 最初に止まる <b>。 パターンが一致しすぎると、適切なものを選択することが解決策になることがよくあります。
正規表現で特殊文字をエスケープするにはどうすればよいですか?
文字通り意味するメタキャラクタの前にバックスラッシュを置きます。 \.、 \*、 \+、 \?、 \(、 \)、 \[、 \]、 \{、 \}、 \^、 \$、 \|、そして \\.ほとんどの言語は、あなたのために文字列全体をエスケープするためのヘルパーも提供します - re.escape() たとえば、python では、文字列がユーザー入力から取得される場合に、手でエスケープするよりも安全です。
正規表現フラグ G、I、および M は何を意味しますか?
g (グローバル) は、最初の試合で停止するのではなく、すべての一致を見つけます。 i (大文字と小文字を区別しない) パターンを大文字と小文字を区別しないようにし、 m (複数行) ^ あんど $ 文字列の開始と終了だけでなく、すべての改行で一致します。 自由に組み合わせるので、 gim 3つすべてを行います。 JavaScript でよくある問題: 再利用 g 通話の正規表現は、キャリーを lastIndex それらの間で、 test() true と false を交互に選択 - パターンを再作成するか、リセットします lastIndex。
正規表現の先読みは何ですか?
先見の明は、何かがそれを消費せずに実行または従わないことを主張します。 foo(?=bar) マッチ foo いつだけ bar 次は来る。 foo(?!bar) 一致しない場合にのみ一致します。 後ろを見て((?<=...)、 (?<!...)) は同じことを逆行し、現代のJavaScript、Python、PCREに上陸しました - しかし、Go& #39; s RE2 ではそうではなく、両方を完全に拒否します。 パスワードルールは古典的な使用法です: ^(?=.*\d)(?=.*[a-z]).{8,}$ アサーションをスタックして、各要件が同じ位置で個別にチェックされます。
電話番号を正規表現と一致させるにはどうすればよいですか?
特定の形式の場合、巧妙ではなく明示的である: ^\(\d{3}\) \d{3}-\d{4}$ マッチ (555) 123-4567。 さまざまなセパレータを許容するために、次のようなオプションを使用できます。 ^\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$。電話番号は国によって乱雑であるため、実際に受け入れる形式のみを検証し、保存する前に数字に正規化します。パターンを信頼する前にライブで構築してテストします。
まとめ
正規表現は、エディターで推測するのではなく、ライブ テスターでパターンを構築し始めた瞬間に、私の最も恐ろしいスキルから最もよく使われるスキルの 1 つになりました。 簡単に始めて、実際の敵対的な入力に対してテストし、壊滅的なバックトラッキングを尊重し、信頼できるパターンの個人ライブラリーを維持します。
ザ・ 正規表現ビルダー on Toolz.dev はそのループを高速化し、リアルタイムマッチング、グループハイライト、フラグトグル - すべてがブラウザで実行されているため、テストデータは非公開のままです。 pattern が JSON を抽出したら、それを に渡します JSON フォーマッタ; Base64 Blob をキャプチャする場合は、 Base64 コンバーター。 または、600 以上の無料ツールをすべて閲覧する Toolz.dev。



