連載
» 2016年10月25日 05時00分 公開

「正規表現」の基本的な使い方をJavaScriptで理解するJavaScript標準ライブラリの使い方超入門(5)(3/5 ページ)

[金城俊哉,著]

RegExpオブジェクトのメソッドで検索する

Onepoint

 正規表現の文字列パターンを作成するRegExpオブジェクトには、検索用のexec()メソッドがあります。ただし、このメソッドは、Stringオブジェクトのmatch()メソッドと異なり、一度パターンマッチした段階で処理を終了します。動作としては、match()メソッドでグローバル検索のgオプションを付けない文字列パターンを使用したときと同じです。

 なお、exec()メソッドはRegExpのインスタンスに対して実行するので、次のように書きます。

Memo gオプションなしで文字列全体に対してパターンマッチしないとどうなるか

 正規表現のgオプションは、「文字列全体に対してパターンマッチさせる」ためのオプションです。なので、gオプションを付けないと、1度パターンマッチした段階で処理が終了することはわかるのですが、それがどういう結果になるのがいまひとつわかりません。

 そこで、本編で作成したURLを検索するプログラムを例に、正規表現パターンのgオプションをなしにして結果を見てみることにしましょう。

パターン文字列をgオプションなしにする(match_URL2.html)
実行結果

 おっと、1個の結果しか表示されません。しかも「undefined」「co.」「/」などの意味不明な文字が表示されています。これはいったいどういうわけなのでしょう。

 まず、1行目の「http://www.system.example.co.jp/」ですが、gオプションを付けない場合は、1度パターンマッチすると処理を終了するので、検索結果が1つなのはわかります。問題は次に続く文字です。

 確かmatch()メソッドは、検索結果を配列で返すのでしたね。検索結果は1つとは限らないので、これはわかります。

 ところが、match()メソッドの仕様として、gオプションがない場合は最初にパターンマッチした文字列に加えて、サブマッチ文字列が設定されている場合はその結果、さらには複数回マッチした文字列があれば対象の文字列を配列で返すのです。

●「サブマッチ文字列」って何?

 パターン文字列の冒頭では、「http(s)?:」のようにすることで、http:でもhttps:でもマッチするようにしています。このときの「(s)」にマッチした文字列が「サブマッチ文字列」です。

 gオプションがない場合は、サブマッチ文字列の結果が配列要素で返されます。例の場合は、サブマッチ文字列にマッチする文字列がなかったので「undefined」(未定義)が返されたというわけです。もし、検索対象が「https:」だった場合は「s」が返されます。

●「複数回マッチした文字列」ってどういうこと?

 正規表現のパターン文字列に複数回、マッチすることです。例題のプログラムでは、「co.」と「/」がこれに当たります。

「複数回マッチした文字列」とは

 複数回マッチした文字列のうち、最後にマッチした文字列が配列に格納されて返されます(次図を参照してみてください)。

複数回マッチした文字列のうち、最後にマッチした文字列が配列に格納されて返される

Hint iオプションを付けない場合

 iオプションは「大文字と小文字を区別しない」ことを指定します。なので、このオプションを付けない場合は、当然ですが大文字と小文字が区別されます。

 パターン文字列を次のようにして、結果を確認してみましょう。

URLを検索する(match_URL3.html)
実行結果

 パターン文字列の冒頭では「http(s)」としていますので、「HTTP」にはマッチしません。


exec()メソッドの書き方

 ちなみに、先のmatch()メソッドの場合と同じようなやり方でexec()メソッドを実行してみると、次のようになります。

match()メソッドと同じやり方でexec()を実行する(exec_befor.html)
実行結果

 実行した結果、検索されたのは最初にパターンマッチしたURLだけです。このあとの表示も含めて、gオプションなしでmatch()メソッドを実行したときと、まったく同じ結果になっています。

実は「賢い」exec()メソッド

Navigator

「ということで、exec()メソッドで検索する場合は、最後にパターンマッチするまで繰り返し実行しないと、マッチしたすべての文字列を取り出すことができないことがわかりました」


Driver

「でも、exec()メソッドを繰り返し実行しても、結局は最初にマッチした文字列を返すだけの繰り返しになるんじゃないですか?」


exec()メソッドには、マッチした文字列の位置を記憶する機能がある。
Navigator

「実はですね、exec()メソッドは『マッチした文字列の位置を記憶する機能』を持っているのです。exec()メソッドの機能というよりは、RegExpオブジェクトの機能なのですが、繰り返し処理の中で実行した場合、2回目の実行の際に『前回マッチした文字列のあとの位置から検索を開始』します」


Driver

「『検索結果を1つしか返さない』というのは欠点のようにも思えましたが、実はこんな機能があったのですね」


Navigator

「ですので、exec()メソッドは文字列を検索するだけでなく、繰り返し中で検索した文字列に対して何らかの処理も加えたいときにとても便利なのです」


while文でexec()メソッドを繰り返し実行する

Driver

「exec()メソッドが前回パターンマッチした位置(の最後)を記憶するのはわかりましたが、これ以上パターンマッチしないときはどうなるんです?」


Navigator

exec()メソッドは、これ以上パターンマッチする文字列がない場合はnullを返してきます。ですので、繰り返し処理を行う場合は、nullが返ってきた時点で処理を終了すればよいことになります」


Driver

「このような処理には、while文が適していますよね」


Navigator

「では、先ほどのプログラムをwhile文に書き換えたパターンを作ってみますね。せっかくですので何か1つ処理を加えることにしましょう。exec()メソッドは、マッチした文字列とその他の情報を配列で返しますが、このときArrayオブジェクトのインスタンスに対しても情報を書き込みます。具体的には、検索結果に基づいてArrayオブジェクトの以下のプロパティの値を設定するんです」


Arrayオブジェクトの正規表現に関するプロパティ
プロパティ 説明
input パターンマッチに使用したパターン文字列を参照します。
index パターンマッチした位置を示す0から始まるインデックスを参照します。
Navigator

「マッチした文字列の抽出に加えて、inputプロパティを参照することでマッチした位置を示すインデックスを取り出して、『○○番目の文字がマッチ』のように書き出すには、こんなふうになります」


while文でexec()メソッドを繰り返す(exec_after.html)
実行結果
Driver

「パターンマッチした文字列をすべて取得することに加えて、何かの処理を付け加えたいときにexec()メソッドを使うといいわけですね」


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。