正規表現とパターンマッチング
作成日 : 2013-01-26
最終更新日 :
オライリーの JavaScript 第6版
を図書館から借りて、
いろいろ調べている。
10 章の正規表現とパターンマッチングは知らないので、少し調べてみた。
基本的な正規表現
正規表現リテラルを作るのがわかりやすい。このリテラルは、/ と / ではさむ。
const re = /sana/;
この正規表現に対してマッチする文字列はどんなものがあるだろうか。
これを調べるには RegExp.prototype.test を使うのがいい。
re.test("malsana"); // true, 文字列 "sana" にマッチする
re.test("malsanulejo"); // false; 文字列 "sana" にマッチしない
正規表現では、メタ文字を使って多くのパターンを表現できる。たとえば、文字クラスといって、
ある範囲の中の文字の一つにマッチングさせることができる。これには角かっこの組 [] を用いる。
例:アルファベットの母音の組 [AEIOUaeiou]
文字クラスには、範囲を表すハイフン - が使える。これは、文字が一定の順序で並んでいることを前提としている。
例:アルファベット大文字 [A-Z]
例:十進法の数字 [0-9]
例:十六進法の数字 [0-9A-Fa-f]
下のフォームは、正規表現と、その正規表現にマッチさせたい文字列を入れ、[テスト]のボタンをクリックすると、
マッチするかしないかをダイアログウィンドウで表示するプログラムである。このとき、正規表現として
ブラウザの JavaScript が受け付けない場合は、「無効な正規表現です」とダイアログウィンドウに表示して終了する。
なお、[ひらがな]から[句読点、記号]
のボタンをクリックすると、それぞれの文字種類を表す文字クラスを正規表現のカラムに表示する。
なお、文字列の置換も参照。
オプションの意味
フォームのオプションの意味について説明する。
- グローバル
- 全体の文字列を見てマッチしたパターンすべてを返す。
- 大文字小文字無視
- このオプションを適用すると、大文字と小文字の区別をしないマッチが行われる。
たとえば、このオプションを適用して正規表現で[a-f] 指定すると [A-F][a-f] が指定されたものと等しい。
- 複数行検索
- 複数行検索に対応する。このオプションを適用すると、
複数行ある文字列の行頭にも正規表現 ^文字列 がマッチし、
同様に複数行ある文字列の行末にも正規表現 文字列$ がマッチする。
このオプションがなければ正規表現の ^文字列 は、複数行あっても文字列の冒頭のみにマッチする。
同様にこのオプションがなければ正規表現の 文字列$ は、複数行あっても文字列の末尾のみにマッチする。
- .で改行にマッチ
- このオプションがなければ任意の1文字を表す正規表現 . は改行文字にはマッチしない。
このオプションを適用すると . に改行文字を含める。
- Unicode のコードポイント
- このオプションがなければ Unicode 16 ビットのコードユニットごとで文字を区切るが、
このオプションを適用すると Unicode のコードポイントごとで文字を区切る。
コードポイントは通常 16 ビットであるが、
サロゲートペアで表現する一部の漢字は 32 ビットである。
どのような文字でも1単位として厳密に認識するにはコードポイントで文字を区切らなければならない。
たとえば、𩸽(ホッケ)、𩹷(イトウ)などの漢字はサロゲートペアで表現されるため、
このオプションなしの場合は2文字としてマッチすることになるが、
このオプションを適用すると1文字としてマッチする。
- 粘着質
-
検索が粘着質 (sticky) であるとは、
文字列内の検索を、正規表現の lastIndex プロパティで示されたインデックスからのみ開始することをいう。
なお、このオプションを適用すると、グローバルオプションは無視される。
JavaScript での正規表現
正規表現クックブック
で、JavaScript では適用されていないとされていた項目が、
2021 年 4 月現在どのような状態にあるか、確認してみた。
新たにサポートしたもの
- 「ドットで改行にマッチ」モード
- 「^と$で改行にマッチ」モード(複数行検索)
- 後読み(lookbehind)
- 否定の後読み(negative lookbehind)
- 名前つきキャプチャ
- 名前付き後方参照
現在でもサポートしていないもの
- ブロックエスケープ
- モード修飾子
- アンカーの一部(\A, \Z, \z)
- Unicdoe (プロパティ|ブロック|スクリプト)
- 絶対最大量指定子
- アトミックグループ
- フリーフォーマットモード
- コメント構文
モード修飾子
(?i)や(?-i)、(?m)のようなモード修飾子は、現在もサポートしていない。これらは「無効な正規表現」とされる。
名前付き後方参照
次のような使い方がある。三好達治の有名な詩「雪」から拝借した。
const snow = '太郎を眠らせ、太郎の屋根に雪ふりつむ';
const regexpTitle = /(?<name>[一-龠]+)を眠らせ、\k<name>/;
const groups = sir.match(regexpTitle).groups;
console.log(groups.name); // 太郎
正規表現の構文
JavaScript モダンプログラミング完全ガイドの pp.140-141 をもとにして、正規表現の構文をまとめる。
文字
- . * + ? { | ( ) [ \ ^ $ 以外の 1 文字
- 文字そのものにマッチ
- \cL。ただし、L は[A-Z][a-z]のどれか
- 文字 L に対応する制御文字
- \cc。ただし、c は [0-9BDPSWbcdfknprstv] のどれでもないこと
- c という文字
文字クラス
- [C1C2...] Ci は文字、範囲 c-d または文字クラス
- C1C2 で表現される文字のどれか
- [^...]
- 文字クラスの補集合
- \p{BooleanProperty}, \p{Property=Value}
- Unicodeプロパティ
- P{BooleanProperty}, \P{Property=Value}
- Unicodeプロパティの補集合
- \d, \D
- 数字[0-9]、その補集合
- \w, \W
- ワード文字 1 つ[a-zA-Z0-9_]、その補集合
- \s, \S
- スペース、その補集合
シーケンスと選択肢
- XY
- Xの文字列とそれに続くYの文字列
- X|Y
- X または Y の文字列
グループ
- (X)
- X のマッチをグループにキャプチャする
- \n
- n 番めのグループにマッチする
- (?<名前>X)
- 与えられた名前で X とのマッチをキャプチャする
- \k名前
- 与えられた名前をもつグループ
- (?: X )
- X をキャプチャせずに丸カッコで囲む
修飾子
- X?
- オプションの X
- X?
- 0 個以上の X、1 個以上の X
- X{n},X{n,},X{m, n},
- n 回の X、n 回の X、n 回の X
- X*? または X+?
- 無欲な修飾子
境界
- ^, $
- 入力の始まりと終わり(もし multiline フラグが有効なら行の始まりと終わり)
- \b, \B
- ワード境界、非ワード境界
参考
まりんきょ学問所 >
JavaScript 手習い >
正規表現とパターンマッチング
MARUYAMA Satosi