正規表現の記号は、どの言語でもおおむね同じです。ところが日本語のテキストを扱うと、同じパターンが言語によって違う結果を返します。\d が全角数字に一致するかどうか、[ぁ-ん] に入らないひらがながあること、\b が日本語の文中でほとんど働かないこと、後読みの書き方に制限がある言語があること。この早見表では記号の一覧に加えて、こうした違いを実際に実行した結果で示します。
表の結果はすべて 2026-10-02 に実行して得たものです。JavaScript は Node.js 22 と 24、Python は 3.12 の re、PCRE2 は 10.49(PHP の preg_* や grep -P が使うライブラリ)、Go は 1.27 の regexp です。「エラー」はそのパターンを受け付けないことを表します。フラグが g・i・m・s だけの例は、本サイトの正規表現テスターに貼り付けると同じ結果になります。このツールはブラウザの RegExp をそのまま使い、u・v フラグのチェックボックスはないため、Unicode プロパティの例はブラウザのコンソールで試してください。
正規表現の記号一覧(早見表)
| 分類 | 記号 | 意味 | 例 |
|---|---|---|---|
| 文字 | . | 改行以外の任意の 1 文字 | 東.都 は「東京都」に一致 |
| 文字クラス | [abc] / [^abc] | いずれか 1 文字 / それ以外 | [^、。]+ で句読点の間を取り出す |
| 文字クラス | [a-z] | 文字コードの範囲 | [ァ-ヺー] でカタカナ |
| 略記 | \d \w \s | 数字・単語文字・空白 | 意味は言語で違う(次の節) |
| 略記 | \D \W \S | それぞれの否定 | \S+ で空白以外の塊 |
| 位置 | ^ / $ | 先頭 / 末尾(m で各行) | ^# で見出し行 |
| 位置 | \b / \B | 単語の境界 / 境界以外 | 日本語の文中では働かない |
| 量指定子 | * + ? | 0 回以上・1 回以上・0 か 1 回 | ゙? で濁点の有無 |
| 量指定子 | {n} {n,} {n,m} | 回数の指定 | \d{3} で 3 桁 |
| 最短一致 | *? +? | できるだけ短く | 「.+?」 でかぎ括弧 1 組ずつ |
| グループ | ( ) / (?: ) | 捕獲する / しない | (\d{4})年 で年だけ取り出す |
| 選択 | | | または | 株式会社|有限会社 |
| 後方参照 | \1 | 1 番目のグループと同じ文字列 | (.)\1 は「ここ」に一致 |
| 先読み | (?=…) / (?!…) | 後ろに続く / 続かない | \d+(?=円) |
| 後読み | (?<=…) / (?<!…) | 前にある / ない | (?<=¥)\d+ |
最短一致の違いは、かぎ括弧で確かめるとわかりやすいです。「はい」と「いいえ」が並んだ文で、「.+」 は最初の「から最後の」までを 1 つとして取り、「.+?」 は「はい」と「いいえ」を別々に取ります。
全角・半角と \d \w \s:言語によって意味が違う
日本語の入力フォームでは、IME の全角モードのまま数字が入力されることがよくあります。ここで \d の意味が言語によって違うことが効いてきます。
| パターン | 対象 | JavaScript | Python | PCRE2 | Go |
|---|---|---|---|---|---|
\d{3}-\d{4} | 〒150-0002 と 150-0002 | 150-0002 | 150-0002 と 150-0002 | 150-0002 | 150-0002 |
\w+ | naïve café | na ve caf | naïve café | na ve caf | na ve caf |
\s+ | 全角スペースを含む a b | 一致(U+3000) | 一致 | 一致しない | 一致しない |
Python の str パターンでは \d が Unicode の 10 進数字すべてに一致するため、全角の 150-0002 も郵便番号として通ります(Python ドキュメント)。JavaScript・PCRE2・Go の \d は 0〜9 だけです。サーバー側を Python、画面側を JavaScript で検証していると、同じパターンなのに片方だけ通る入力が生まれます。対策は 2 つあります。どちらの言語でも [0-9] と書いて意味をそろえるか、検証の前に NFKC 正規化で全角英数字を半角にそろえるかです。JavaScript なら '150-0002'.normalize('NFKC') で 150-0002 になります。全角スペースは NFKC で半角スペースになり、「ガ」のような半角カナは全角の「ガ」になります。Python では re.ASCII フラグを付けると \d・\w・\s が ASCII だけになります。
全角スペースの扱いも言語で違います。JavaScript の \s と String.prototype.trim() は U+3000 を空白として扱うので、' 全角 '.trim() は 全角 になります。Go と PCRE2(UCP なし)の \s は全角スペースに一致しないので、前後の空白を消すなら [\s ] のように明示します。
全角英数字だけを取り出すときは、範囲で書きます。[A-Za-z0-9]+ は「ABC123とABC」から ABC123 だけを取ります。全角の記号まで含めるなら [\uFF01-\uFF5E]+(全角の「!」から「~」まで)で、「Wi-Fi(5G)」が丸ごと一致します。ただし \u の書き方は JavaScript と Python のもので、PCRE2 と Go では \x{FF01} と書きます。
ひらがな・カタカナ・漢字を範囲で書くときの落とし穴
「ひらがなだけ」「カタカナだけ」を判定する正規表現は、範囲指定で書かれることが多いです。よく見る範囲には、それぞれ漏れがあります。
| 書き方 | 対象 | 結果 | 漏れるもの |
|---|---|---|---|
[ぁ-ん]+ | ゔぁいおりん ゕ ゖ ー | ぁいおりん | 「ゔ」(U+3094)、小書きの「ゕ」「ゖ」、長音符「ー」 |
[ぁ-ゖ]+ | 同上 | ゔぁいおりん、ゕ、ゖ | 長音符「ー」 |
[ァ-ヶー]+ | ヴァイオリン ヷ ヺ | ヴァイオリン | 「ヷ」〜「ヺ」(U+30F7〜U+30FA) |
[ァ-ヺー]+ | 同上 | ヴァイオリン、ヷ、ヺ | なし |
[ヲ-゚]+ | データ パソコン | データ、パソコン | 半角カナは U+FF66〜U+FF9F で別の範囲 |
[一-龠]+ | 𠮷野家 佐々木 〆切 | 野家、佐、木、切 | 「𠮷」(U+20BB7)、「々」、「〆」 |
長音符「ー」(U+30FC、KATAKANA-HIRAGANA PROLONGED SOUND MARK)は、ひらがなでもカタカナでもない共通の文字です。「すーぱー」をひらがなとして判定したいなら、範囲に ー を足す必要があります。漢字の範囲 [一-龠] は古くから使われる書き方ですが、「々」(U+3005)も「〆」(U+3006)も範囲の外にあり、「𠮷」のように U+FFFF を超える漢字は JavaScript の u なしの正規表現では 2 つのコード単位に分かれるため、範囲では表せません。
範囲を覚えるより確実なのが Unicode の文字種(Script)プロパティです。JavaScript では u か v フラグが必要です。
パターン(u フラグ) | 対象 | 結果 |
|---|---|---|
\p{sc=Hira}+ | すーぱー | す、ぱ(「ー」は Script=Common) |
\p{scx=Hira}+ | すーぱー | すーぱー(Script_Extensions には「ー」が含まれる) |
\p{sc=Han}+ | 𠮷野家 佐々木 〆切 | 𠮷野家、佐々木、切 |
\p{scx=Han}+ | 同上 | 𠮷野家、佐々木、〆切 |
\p{Script=Katakana}+ | カタカナとカタカナ | カタカナ、カタカナ(半角カナも含む) |
sc(Script)は文字の主な文字種、scx(Script_Extensions)はその文字が一緒に使われる文字種も含めた集合です。日本語の判定では scx のほうが期待に近い結果になります。PCRE2 は 10.40 から、\p{Hiragana} のように種別を省いた書き方を scx として扱います(pcre2pattern)。Python の標準 re には \p{…} がなく、bad escape \p というエラーになります。Python で文字種を使うならサードパーティの regex モジュールを入れるか、範囲で書きます。
日本語の文章で \b が使えない理由
\b は「単語文字(\w)とそれ以外の境目」に一致します。英語では単語の前後に空白や記号があるので、\bcat\b は「concat」の中の cat を除いて取り出せます。日本語は単語を空白で区切らないので、この仕組みが働きません。
JavaScript・PCRE2・Go では日本語の文字は \w に入らないため、「これは本」のどこにも境界がなく、\bは\b は一致しません。Python では逆にすべての文字が \w なので、\b\w+\b は「東京都の天気」を 1 語として返します。どちらの言語でも、助詞の「は」や単語「東京」を正規表現の境界で切り出すことはできません。単語単位で処理したいときは、MeCab や Sudachi などの形態素解析器で分かち書きしてから正規表現を使います。単に「東京」という文字列を探すだけなら、\b を付けずに 東京 と書けば十分です。
郵便番号・電話番号・金額を抜き出す
入力チェックでよく使うパターンを、テスト用の入力と一緒に挙げます。複数行の入力は m フラグを付けて 1 行ずつ判定しています。
| 用途 | パターン | 通る | 通らない |
|---|---|---|---|
| 郵便番号(ハイフン任意) | ^\d{3}-?\d{4}$ | 150-0002、1500002 | 150-00002 |
| 携帯電話番号 | ^0[6-9]0-[1-9]\d{3}-\d{4}$ | 090-1234-5678 | 080-0123-4567、070-1234-567、03-1234-5678 |
| 固定電話番号(10 桁) | ^(?=[0-9-]{12}$)0[1-9][0-9]{0,3}-[0-9]{1,4}-[0-9]{4}$ | 03-1234-5678、0466-12-3456 | 090-1234-5678、03-123-45678 |
携帯電話番号の形は総務省の電気通信番号計画にもとづきます。音声伝送携帯電話番号は「060/070/080/090 CDE FGHJK(C は 0 を除く)」の 11 桁です(総務省 電気通信番号制度)。060 は令和 6 年 12 月に追加された番号で、総務省の案内ページでは事業者側の対応が終わったあと順次使えるようになるとされています(携帯電話番号への060番号の追加)。古いパターン ^0[789]0 のままだと、060 の番号を受け付けません。また C は 0 を除く という規則から、080-0123-4567 は形として存在しない番号になります。
固定電話番号は「0 ABCDE FGHJ」の 10 桁です。ハイフンの位置は地域によって違う(03-1234-5678、0466-12-3456)ので、ハイフンの位置では桁数を決められません。そこで、先読み (?=[0-9-]{12}$) でハイフン込み 12 文字(数字 10 桁)を先に確かめています。Go は先読みを使えないので、Go ではハイフンを除いてから ^0[1-9][0-9]{8}$ で桁数を確認するのが簡単です。
金額の抜き出しは先読みと後読みの典型的な使い道です。
\d[\d,]*(?=円) は「税込1,980円(本体1,800円)」から 1,980 と 1,800 を取り出し、(?<=[¥¥])\d[\d,]* は半角の ¥ と全角の ¥ のどちらの後ろの数字も取ります。円記号は半角(U+00A5)と全角(U+FFE5)が混在しやすいので、文字クラスに両方を入れておきます。
名前付きグループと後読み:JavaScript と Python の書き方
同じ意味の正規表現でも、名前付きグループの書き方は言語で違います。
| 機能 | JavaScript | Python | PCRE2 | Go |
|---|---|---|---|---|
| 名前付きグループ | (?<y>…) | (?P<y>…) | 両方 | 両方 |
| 置換での参照 | $<y> | \g<y> | 呼び出す言語による | ${y} |
| 後読み | 長さ自由 | 固定長のみ | 上限のある可変長 | 使えない |
後方参照 \1 | 使える | 使える | 使える | 使えない |
(?<y>\d{4})年(?<m>\d{1,2})月(?<d>\d{1,2})日 は JavaScript・PCRE2・Go で「2026年10月2日」に一致しますが、Python では unknown extension ?<y というエラーになります。Python 向けの (?P<y>…) は逆に JavaScript でエラーになります。
後読みの制限は日本語のパターンで引っかかりやすいところです。
(?<=税込|税抜)\d[\d,]* は選択肢がどちらも 2 文字なので Python でも動きます。ところが送り仮名を付けて (?<=税込み|税抜)\d[\d,]* にすると、3 文字と 2 文字で長さがそろわず、Python は look-behind requires fixed-width pattern で拒否します。JavaScript は長さの違う後読みも受け付け、PCRE2 は 10.43 以降、最大長が決まっていれば受け付けます。どの言語でも動かしたいなら、後読みをやめて (?:税込み|税抜)(\d[\d,]*) のようにグループで捕獲するのが確実です。
Python で名前付きグループを使うと、取り出した値に名前でアクセスできます。
import re, unicodedata
m = re.fullmatch(r'(?P<y>\d{4})年(?P<m>\d{1,2})月(?P<d>\d{1,2})日', '2026年10月2日')
print(m['y'], m['m'], m['d'])
# 全角の郵便番号は NFKC で半角にそろえてから判定する
print(unicodedata.normalize('NFKC', '150-0002'))
print(bool(re.fullmatch(r'[0-9]{3}-[0-9]{4}', '150-0002')))
フラグと Unicode プロパティ(u / v)
| JavaScript | Python | 意味 | 正規表現テスター |
|---|---|---|---|
g | findall / finditer | すべての一致を探す | あり(常に全件検索) |
i | re.I | 大文字小文字を区別しない | あり |
m | re.M | ^ $ が各行に一致 | あり |
s | re.S | . が改行にも一致 | あり |
u | (str では常に有効) | コードポイント単位、\p{…} を使う | なし |
v | なし | u に加えて集合演算 | なし |
y | pattern.match(s, pos) | 指定位置からだけ一致 | なし |
d | match.span() | 一致位置を記録 | なし |
u フラグがないと、JavaScript は文字列を UTF-16 のコード単位で扱います。「𠮷」や絵文字は 2 単位になり、. 1 つでは一致しません。\p{L} も u なしでは p{L} という文字列として扱われます。v フラグ(Chrome 112、Firefox 116、Safari 17 以降。MDN)では、文字クラスの中で差集合 -- と積集合 && が書けます。たとえば [\p{Nd}--[0-9]] は「ASCII 以外の 10 進数字」なので、全角数字を見つけて警告するのに使えます。
const zenkakuDigit = /[\p{Nd}--[0-9]]/v;
console.log(zenkakuDigit.test('電話123'), zenkakuDigit.test('電話123'));
console.log('150-0002'.normalize('NFKC'));
console.log(' 全角 '.trim());
Google スプレッドシートと Go は RE2
Google スプレッドシートの REGEXMATCH・REGEXEXTRACT・REGEXREPLACE は RE2 という正規表現エンジンを使い、Unicode 文字クラスのマッチングには対応していません(REGEXMATCH ヘルプ)。Go の regexp も同じ RE2 の構文です。RE2 は入力の長さに比例する時間で必ず終わる代わりに、次の機能を持ちません。
- 先読み・後読み(
(?=…)、(?<=…)など) - 後方参照(
\1。英語の重複語を探す\b(\w+) \1\bも Go ではエラー) - 強欲な量指定子(
\d++)とアトミックグループ((?>…))
この記事の表で Go が「エラー」になっている例は、スプレッドシートでもそのままでは使えないと考えてください。たとえば金額の抜き出し \d[\d,]*(?=円) は、スプレッドシートでは ([\d,]+)円 のように「円」まで含めて一致させ、数字の部分をグループで取り出す形に書き換えます。
逆に JavaScript・Python・PCRE2 はバックトラック型のエンジンで、^(a+)+$ のように量指定子を入れ子にしたパターンは、一致しない長い入力で処理時間が急に伸びます。ユーザーが入力したテキストに正規表現をかけるときは、入力の長さに上限を設けておくと安全です。
正規表現テスターで確かめる手順
パターンを本番のコードに入れる前に、通るべき入力・通ってはいけない入力・迷う入力(空文字、全角数字、末尾の改行、絵文字)を並べて試すのが近道です。本サイトの正規表現テスターでは次のように確かめます。
- パターン欄に
^\d{3}-?\d{4}$を入れ、mにチェックを入れる。 - テスト文字列に
150-0002、1500002、150-00002、150-0002を 1 行ずつ貼る。 - 状態表示が「2 件マッチしました。」になり、ハイライトで最初の 2 行だけが一致していることを確認する。全角の行が一致しないのは、ブラウザの JavaScript の
\dが ASCII の数字だけだからです。
一覧に表示される位置(index)は JavaScript と同じ UTF-16 の位置なので、前に「𠮷」や絵文字があると 2 ずつ進みます。名前付きグループも「グループ 1」「グループ 2」のように番号で表示されます。u・v フラグが必要なパターンは、このツールではなくブラウザのコンソールか Node.js で確かめてください。