JavaScriptで覚える 正規表現について

似たような形式の文字列を検索する際、正規表現が使えると、処理をコンパクトにまとめることが可能になります。

例えば、文中からHTMLタグを探すとき、例えば「<p>」のように、文字列で検索すると思いますが、この場合pタグしか検索できず、他のタグも検索しようとすると、タグの種類の数だけ検索の処理を書かないといけません。

HTMLタグは『<』+『タグ名』+『>』で構成されていて、タグ名の箇所が変わるものの、『<』と『>』で囲まれているという規則性(=パターン)があります。文字列ではなくパターンを定義する『正規表現』を使うことで、1回の検索処理で不特定多数のHTMLタグを検索することが可能になるのです。

少しわかりづらくなってしまいましたが、正規表現については「習うより慣れよ」です。JavaScriptでの実例を交えながら簡単に紹介いたします。

そもそも正規表現とは?

正規表現とは特殊文字(メタキャラクタ)を使って文字列のパターンを表現する方法で、規則性のある文字列を検索する際の強力な味方となってくれるものです。

英語だと「Regular Expression」と書き、プログラミング言語ごとに違いはありますが、RegExpやRegexと略されます。

通常の検索は、検索する文字列と全く同じ文字列しか探せませんが、正規表現検索は、文字列ではなくパターンで検索するので、同じ規則性を持つ文字列を全て見つけられます。

誤解を恐れず簡単に言うと、「ひとつの検索語で複数の言葉を探すための仕組み」なのです。

よく使う正規表現の特殊文字一覧

先述の通り、正規表現では文字と特殊文字を使って検索語のパターンを作ります。例えば、半角英数字を表す『\w』、数字を表す『\d』といった文字を抽象化し代替する特殊文字があります。他にも、冒頭を表す『^』、末尾を表す『$』、文字、特殊文字の繰り返しを示す『*』や『+』、という特殊文字が用意されています。

文字

特殊文字 意味
. ピリオド 改行を以外の全ての1文字にマッチする特殊文字です。
\ バックスラッシュ 正規表現では、アルファベットと組み合わせて特殊文字を作ったり、特殊文字と合わせて、効果を打ち消したり、正規表現において重要な特殊文字です。フォントによっては半角の円マーク『\』で表示される場合もありますが同じものです。
\d 数字(0~9)の1文字にマッチする特殊文字です。
\D 数字(0~9)以外の文字にマッチする特殊文字です。
\w 大文字小文字のアルファベット(a~z、A~Z)、数字(0~9)、アンダーバーのいずれかにマッチする特殊文字です。
\W 大文字小文字のアルファベット(a~z、A~Z)、数字(0~9)、アンダーバー以外の1文字にマッチする特殊文字です。
\s 空白文字(全角スペース、半角スペース、タブスペース、改行)にマッチする特殊文字です。
\S 空白文字以外にマッチする特殊文字です。
\n 改行にマッチする特殊文字です。

 

文字集合

特殊文字 意味
[abc] []内に含まれる文字、または特殊文字のどれかにマッチします。
[^abc] [^]の範囲に含まれる文字、または特殊文字以外にマッチします。

 

文字位置

特殊文字 意味
^ パターンの始めに使用します。直後の文字が文字列の先頭の場合にマッチします。
$ パターンの終わりに使用します。直前の文字が文字列の末尾にある場合にマッチします。

 

グループ化と後方参照

特殊文字 意味
(abc) ()内に含まれる文字列にマッチし、マッチした内容を記憶します。例だと、abcを記憶し、regexpオブジェクトのプロパティ、$1に代入します。
()の出現順に$1から$9まで順番に代入され、後から参照することが可能になります。これを後方参照と呼びます。
\N Nの箇所には1から9いずれかの数字が入ります。パターン内でグループ化した内容を後方参照する際に使用します。
パターン内で後方参照する場合、$ではなく\が使われることにご注意ください。
(?:abc) ()内に含まれる文字列にマッチしますが、マッチした内容は記憶されないため、後方参照することができません。

 

量指定子

特殊文字 意味
* 直前の文字、または特殊文字の0回以上の繰り返しにマッチします。
+ 直前の文字、または特殊文字の1回以上の繰り返しにマッチします。
? 直前の文字、または特殊文字の0文字もしくは1文字にマッチします。
{n} nには整数が入ります。直前の文字のn回の繰り返しにマッチします。

 

正規表現のオプションフラグ

正規表現はオプションフラグを設定することで、検索の方法を変更可能です。よく使うものだと、マッチする文字列をすべて取得させるオプション、大文字小文字を区別しないでマッチさせるオプションなど。現在JavaScriptの正規表現には5つのオプションフラグがありますが、ブラウザごとの対応状況も考え、主に下記3つのオプションフラグを使用されます。

下記に登場しないフラグについては使用頻度が低いこともありますので、初めは覚えず、必要になった際にMDNなどを参照することをお勧めします。
正規表現オブジェクトについて:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp

g

gフラグ(グローバルサーチフラグ)。マッチする文字列すべてを検索するためのオプションフラグです。正規表現では通常、最初にマッチした文字列しか取得しませんが、gフラグを設定することで、マッチする文字列全てを取得させることが可能になります。

i

iフラグ(イグノアケースフラグ)。アルファベットの大文字と小文字を区別しないで検索するためのオプションフラグです。iフラグを設定することで、特殊文字以外のアルファベットの大文字と小文字を無視して検索をさせることが可能になります。

m

mフラグ(マルチラインフラグ)。行単位で検索を行うためのオプションフラグです。特殊文字の『^』と『$』は、通常、文字列を冒頭と末尾を示しますが、mフラグを設定することで、各行の冒頭と末尾を示すようになります。

JavaScriptで正規表現を使う方法

JavaScriptで正規表現を使う方法は2種類あります。『正規表現リテラル』を使う方法と、『RegExpオブジェクト』を使う方法です。
各行冒頭のJavaScriptにマッチする正規表現を例に挙げ、それぞれ次のように定義します。

正規表現リテラルで定義する方法


  var pattern = /^JavaScript/gm;

パターンをデリミタで囲むことで定義します。デリミタとは、「区切り文字」という意味で、JavaScriptの正規表現リテラルは「/(スラッシュ)」が使われます。オプションフラグは末尾のスラッシュの直後に記載します。

注意点

冒頭と末尾がスラッシュになっていなければならず、また、パターン中のスラッシュは、正規表現の終わりだと認識されてしまうため、エスケープしなければいけません。

エスケープとは、特殊文字の効果を消して、その文字のまま認識させること。エスケープしたい文字の前にバックスラッシュを置くことで実現します。

例:URLのプロトコルにマッチする正規表現リテラル


  var pattern = /^htts?:\/\//

URLは文字列中にスラッシュがほぼ確実に出てくるので、正規表現で検索したい場合、エスケープ忘れに注意が必要です。

RegExpオブジェクトで定義する方法


  var pattern = new RegExp(‘^JavaScript’,’gm’);

パターンの文字列をRegExpオブジェクトの第1引数に持たせて定義します。第2引数はオプションフラグを設定するためにありますが省略も可能です。

注意点

パターン中で、バックスラッシュを使っている場合はエスケープする必要があります。

例:abc.txt、ade.txt、bcd.txtの中で、「a」で始まって「.txt」で終わる半角英数の文字列にマッチする正規表現


  var pattern = new RegExp(‘a\\w*?\\.txt’,’g’);

上記の正規表現部分を最小単位に分解すると次のようになります。

  • 「a」 文字 a
  • \w」特殊文字 半角英数
  • 「*」 特殊文字 直前の文字もしくは特殊文字の0回以上の繰り返し
  • 「?」 特殊文字 繰り返し記号と組み合わせることで最短マッチの意味になります。
  • \.」 文字 .(ピリオド)をエスケープ
  • 「txt」 文字 txt

この中で、「\w」と「\.」にはバックスラッシュが使われていますので、これらはエスケープし、それぞれ、「\\w」、「\\.」と表記します。

RegExpオブジェクトで定義する場合でバックスラッシュを使う際は2つ続ける必要があると覚えておくと間違いがないはずです。

JavaScriptで正規表現が活躍する場面

JavaScriptで正規表現を活用する場合はmatchやreplaceなどの関数が使われます。matchは、正規表現でマッチした文字列が返され、replaceは正規表現でマッチした文字列を指定の文字列と置き換えた結果が返されます。

フォームの入力内容が規定のフォーマットに沿っているかチェックする際などに活躍します。ifとmatchを組み合わせて、パターンにマッチすれば通して、そうでなければ、エラーを出す。という処理を書くことができます。

例:メールアドレスの簡易チェック

簡易的なメールアドレスのフォーマットチェックの例を交えながら紹介いたします。まずメールアドレスの形を分解すると、次のような形になります。


  ローカル部@ドメイン

ローカル部、並びにドメインで使用できるのは半角英数+記号のみです。今回は簡易的なチェックなので使用できる記号も絞り「-」「_」「.」のみが使われているアドレスの入力を受け付ける正規表現を作ります。

まずローカル部は文字列冒頭から始まり、使える文字は、半角英数、「-」、「_」、「.」とすると次のパターンでローカル部を表現できます。


  ^[-\.\w]+

上記パターンが、@マークが出現するまで続くので、次の文字を加えます。


  ?@

ドメイン部に使える文字も半角英数、「-」、「.」、「_」だと仮定して、最後まで繰り返されます。


  [-\.\w]+?$

それぞれを合わせて、次の形が上記の条件に合う正規表現です。


  /^[-\.\w]+?@[-\.\w]+?$/

実際に使用できる記号は他にもありますので、これだけで全てのメールアドレスを網羅できるかといえば、そのようなことはありません。完全に調べたいと思ったらさらに複雑な正規表現が必要なのでご注意ください。

まとめ

  • 半角円マーク『\』とバックスラッシュ『\』はフォントが違うだけで同じもの。
  • JavaScriptで正規表現を使う場合は、正規表現リテラル、もしくは正規表現オブジェクトを使って定義する。
  • 定義する際、文字のエスケープが必要な場合がある。
  • 正規表現のパターンはreplace関数、match関数などで使用可能できる。

正規表現をテキストエディタなどもありますが、JavaScriptとは実装が違っている部分があるため、ご注意ください。
プログラム内での検索の幅が広がる正規表現。基本だけでも覚えておくと非常に強い味方になります。

すべての人にインターネット
関連サービス