正規表現とは何か|書き方の基本と、思いどおりにマッチしないときの直し方

正規表現は「文字列の形をことばで書く」仕組みです。記号を暗記する前に、文字の種類・繰り返し・位置・グループという4つの部品に分けて読むと、他人が書いたパターンも読めるようになります。書き方の基本と、思いどおりにマッチしないときの原因の絞り込み方をまとめました。

🔍 正規表現テストを開く正規表現のマッチ結果をハイライト表示し、キャプチャグループや置換結果をその場で確認できます。

使い方

正規表現チェッカーの画面は、上から「パターン」「フラグ」「テスト対象テキスト」「置換」の順に並んでいます。まずパターン欄に正規表現を入れ、テスト対象テキスト欄に確かめたい文章を貼り付けてください。入力した時点でマッチした部分が本文中にハイライトされ、その下にマッチ一覧とキャプチャグループの値が並びます。実行ボタンを押す操作はありません。パターンを1文字書き換えるたびに結果が付いてくるので、思いどおりにならない箇所を1文字ずつ削って原因を挟み撃ちにできます。

正規表現をこれから覚える段階なら、いきなり目的のパターンを書こうとしないほうが早く進みます。最初にテスト対象テキストへ「拾いたい文字列」と「拾いたくない文字列」を両方貼り、わざと広すぎるパターン(たとえば .+ )から始めてください。全部にマッチする状態からスタートして、余計なものが外れるまで条件を足していくと、どの記号がどこを削ったのかが画面上で確認できます。逆に、狭いパターンから書き始めて1件もマッチしない状態が続くと、どこが悪いのか手がかりが得られません。

フラグは、パターンの意味そのものを変えるスイッチです。よく使うのは5つで、i は大文字と小文字の違いを無視します。m は複数行モードで、後述する ^ と $ が行ごとの先頭・末尾を指すようになります。s はドット(.)が改行にもマッチするようにします。u は文字を Unicode の単位で解釈し、絵文字や一部の漢字を1文字として扱えるようにします。g は全体を対象にするフラグですが、本ツールのマッチ一覧とハイライトは g の有無に関わらず常にテキスト全体を走査します。g が実際に効くのは置換結果のほうで、外すと最初の1件だけ、付けると全件が置き換わります。

置換欄は、パターンで取り出した部分を別の文字列に書き換えたいときに使います。$1・$2 と書くと、パターン内の丸かっこで囲んだ1番目・2番目の部分がそこに入ります。名前付きグループを使った場合は $<name> の形でも参照できます。たとえば日付の並びを入れ替える、全角の記号を半角へそろえる、といった一括置換を、エディタや本番のデータに適用する前にここで確かめられます。置換結果は画面に表示されるだけで、元のテキストは書き換わりません。

入力したパターンとテキストは、すべてブラウザの中だけで処理されます。判定にはブラウザ標準の RegExp と matchAll() / replace() をそのまま使っており、当サイトのサーバーへは送信していません。そのため、公開前の原稿や社内のログを貼っても、内容が外部へ出ることはありません。ただし、共有パソコンで使ったあとに画面をそのまま残さないなど、端末側の扱いには通常どおり注意してください。

仕組みと考え方

正規表現とは、文字列の「形」を短い記号の並びで書き表すための書式です。「ここに数字が4つ並び、次にハイフンが1つ来て、また数字が2つ並ぶ」という説明を、\d{4}-\d{2} と書く。それだけの仕組みです。検索窓に打ち込む普通のキーワード検索が「この文字列そのもの」を探すのに対して、正規表現は「この条件に当てはまる文字列すべて」を探せます。日付・郵便番号・メールアドレス・ログの行頭など、中身は毎回違うのに形だけは決まっているものを扱うときに効きます。

記号は数十個ありますが、丸暗記する必要はありません。正規表現の部品は、役割で見ると次の4種類しかないからです。他人が書いた長いパターンも、この4つに分解しながら左から読んでいくと意味が取れます。

  • 文字の種類を指定するもの … \d は数字1文字、\w は英数字とアンダースコア1文字、\s は空白文字1文字、. は改行以外の任意の1文字。[abc] と書けば a か b か c のどれか1文字、[a-z] なら小文字1文字、[^0-9] なら数字以外の1文字を表す。
  • 繰り返しの回数を指定するもの … * は0回以上、+ は1回以上、? は0回か1回、{3} はちょうど3回、{2,5} は2回以上5回以下、{2,} は2回以上。直前の1つの部品に対して掛かる。
  • 位置を指定するもの … ^ は先頭、$ は末尾、\b は単語の切れ目。位置そのものを指すだけで、文字を消費しない点が他と違う。
  • まとめ方を指定するもの … (...) は複数の部品を1つにまとめ、同時に「あとで取り出せる部分」として記録する。| はどちらか一方という意味で、a|b なら a か b に当たる。(?:...) は、まとめるだけで取り出しはしない書き方。

この4種類を組み合わせると、\d{3}-\d{4} で郵便番号の形、^https?:// で「http:// か https:// で始まる」という条件、(\d{4})-(\d{2})-(\d{2}) で年・月・日を別々に取り出す、といったパターンが書けます。最後の例のように丸かっこで囲んだ部分はキャプチャグループと呼ばれ、マッチ一覧では「グループ1」「グループ2」として値が表示されます。置換欄で $1 と書いたときに入るのが、この値です。

グループが増えてくると番号を数えるのが面倒になるので、(?<year>\d{4}) のように名前を付けられます。名前付きグループを使うと、パターンが長くなっても「どこが年か」が読んで分かり、置換側でも $<year> と書けます。番号は途中に丸かっこを足すとずれますが、名前はずれません。編集する予定のあるパターンほど、名前を付けておく価値があります。

もう一つ、繰り返しには貪欲(greedy)と非貪欲(lazy)という性質があります。* や + は既定で貪欲、つまり「マッチできる限り長く取る」動きをします。たとえば <b>太字</b>と<b>強調</b> というテキストに <b>.*</b> を当てると、最初の <b> から最後の </b> までが丸ごと1件としてマッチします。途中で止まってほしいときは、*? や +? のように ? を付けた非貪欲の書き方にすると、条件を満たす最短の範囲で止まります。思ったより広くマッチしたときに最初に疑うのは、たいていこれです。

エスケープ(\ を前に付けること)も避けて通れません。. + * ? ( ) [ ] { } ^ $ | \ / の各記号は正規表現にとって意味を持つため、文字そのものとして探したいときは \. \+ のように \ を前に置きます。「ドットで区切られた文字列を探したいのに、どこにでもマッチしてしまう」という詰まり方は、この . を素のまま書いていることが原因です。

本ツールが動かしているのは JavaScript の正規表現エンジンです。基本的な書き方はどの言語でもほぼ共通ですが、細部は言語ごとに違います。後読み((?<=...))の対応状況、名前付きグループの書き方、\d が全角数字を含むかどうかといった点は、PHP(PCRE)・Python・Java などで挙動が分かれることがあります。ここで組み立てたパターンを他の言語へ移すときは、移した先でも同じ結果になるかを一度確かめてください。

使いどころ・注意点

正規表現が向いているのは、形が決まっていて、しかも手作業だと数が多すぎる仕事です。ログから特定のエラー行だけを抜き出す、原稿の全角英数字を半角にそろえる、CSVの1列目が特定の書式になっているかを点検する、エディタの一括置換で語尾の表記ゆれを直す。どれも「1件なら目視で終わるが、1000件あると無理」という種類の作業で、こういう場面でこそ効きます。

逆に、向いていない対象もはっきりしています。HTMLやXMLのような入れ子構造を正規表現だけで正しく解析することはできません。タグの中にタグが入る深さに制限がないため、「対応する閉じタグ」を表現しきれないからです。簡単な抜き出しなら動いてしまう分たちが悪く、例外的なHTMLに当たったところで壊れます。同じ理由で、JSONの解析にも使うべきではありません。それぞれ専用のパーサーを使ってください。

メールアドレスの検証も、正規表現だけで完結させようとしないほうが無難な領域です。仕様上は正規表現で書ける形ですが、厳密に書くと極端に長くなり、しかも正しいアドレスを弾いてしまう事故が起きます。実務では「@ が1つあり、その前後が空でない」程度の緩い確認にとどめ、本当に届くかどうかは確認メールの送信で確かめる、という組み立てが一般的です。

書いたパターンが思いどおりに動かないときは、次の順で疑うと原因が早く割れます。まず、広くマッチしすぎている場合は貪欲マッチです。.* を .*? に変えるか、そもそも . ではなく具体的な文字クラス([^<] など)を使うと収まります。次に、マッチ件数が異様に多い場合は、空文字にマッチできるパターンになっていないかを見ます。a* のように「0回以上」だけで構成された部分があると、文字が無い位置にも空文字としてマッチするため、件数が文字数ぶんまで膨らみます。1文字以上を必須にする + に変えるのが基本の直し方です。

1件もマッチしない場合は、フラグとエスケープの2つを順に確認してください。大文字小文字の違いなら i、行ごとの先頭・末尾を見たいなら m、改行をまたいで取りたいなら s が要ります。それでも当たらないなら、パターンの記号がエスケープ漏れを起こしていないか、あるいは全角スペースや改行コードの違いのように、画面では見えない差がテキスト側にないかを見ます。パターンを後ろから1つずつ削り、どこでマッチし始めるかを見るのが確実です。

性能面の注意も1つあります。(a+)+ のように、繰り返しの中にさらに繰り返しを入れた形は、マッチしない入力を与えたときに試行回数が爆発的に増え、処理が固まったように見えることがあります。破滅的バックトラッキングと呼ばれる現象で、外部から入力された文字列を正規表現で検証するサーバー側の処理では、これが可用性の問題につながります。入れ子の繰り返しを避け、必要な範囲を具体的な文字クラスで区切るのが予防策です。本ツールでも、巨大な入力と広すぎるパターンの組み合わせでは処理に時間がかかるため、まず短い抜粋で形を固めてから全文に当てることをおすすめします。

最後に、一括置換を本番のデータへ適用する前の手順です。置換は取り消しが効かない場面が多いので、まず本ツールの置換欄で結果を目で確かめ、次に対象データの控えを取り、それから実行してください。特に g フラグの有無で「1件だけ置換された」「全部置換された」が変わる点は、エディタやプログラム側の設定でも同じ落とし穴になります。件数が想定と合っているかを、置換前に必ず一度見ておくと安全です。

よくある質問

正規表現とは、ひとことで言うと何ですか?

文字列の「形」を記号で書き表すための書式です。「数字が4つ、ハイフン、数字が2つ」といった条件を \d{4}-\d{2} のように短く書き、その形に当てはまる文字列をまとめて探したり置き換えたりできます。

記号が多すぎて覚えられません。どこから覚えればよいですか?

文字の種類(\d \w \s . [ ])、繰り返し(* + ? { })、位置(^ $ \b)、まとめ方(( ) |)の4種類に分けて見ると、覚える量が大きく減ります。まず \d と + と ^ $ の3つだけで書ける範囲から始め、必要になった記号をその都度足していくのが現実的です。

思ったより広い範囲がマッチしてしまいます。

* や + は既定で「できる限り長く」マッチする(貪欲)ためです。*? や +? のように ? を付けると最短で止まります。.* のかわりに [^<]* のような具体的な文字クラスを使う方法も有効です。

マッチ件数が文字数と同じくらいになってしまいます。

a* のように0回以上だけで構成されたパターンは、文字が無い位置にも空文字としてマッチします。1文字以上を必須にする a+ へ変えてください。

置換したら1件しか置き換わりませんでした。

g(グローバル)フラグが外れています。本ツールではマッチ一覧とハイライトは常に全体を走査しますが、置換結果だけは g の有無をそのまま反映します。全件を置き換えたいときは g を付けてください。

ここで作ったパターンを PHP や Python でそのまま使えますか?

多くの場合は動きますが、保証はできません。本ツールは JavaScript の正規表現エンジンを使っており、後読みの記法や名前付きグループの書き方など、言語ごとに細部の仕様が異なります。移した先の環境でも一度テストしてください。

HTMLからタグの中身を取り出すのに使ってよいですか?

その場かぎりの抜き出しなら使えますが、継続して動かす処理には向きません。入れ子の深さに制限がない構造は正規表現では正しく表現できず、例外的なHTMLで壊れます。HTMLパーサーを使ってください。

入力したテキストは外部に送信されますか?

送信しません。マッチ判定も置換もブラウザ内の JavaScript だけで行っており、パターンとテキストが当サイトのサーバーへ送られることはありません。

この記事を共有

← 使い方ガイドの一覧へ戻る