「正規表現」の基本的な使い方をJavaScriptで理解する:JavaScript標準ライブラリの使い方超入門(5)(3/5 ページ)
JavaScriptの標準仕様としてビルトインされている主なオブジェクトの使い方を紹介する連載。今回は、正規表現について。Stringのsearch、match、replaceやRegExpのexecなどメソッドにおける文字列検索や置換の仕方、エスケープ文字や改行などのパターンマッチの基本を解説。
RegExpオブジェクトのメソッドで検索する
正規表現の文字列パターンを作成するRegExpオブジェクトには、検索用のexec()メソッドがあります。ただし、このメソッドは、Stringオブジェクトのmatch()メソッドと異なり、一度パターンマッチした段階で処理を終了します。動作としては、match()メソッドでグローバル検索のgオプションを付けない文字列パターンを使用したときと同じです。
なお、exec()メソッドはRegExpのインスタンスに対して実行するので、次のように書きます。
Memo gオプションなしで文字列全体に対してパターンマッチしないとどうなるか
正規表現のgオプションは、「文字列全体に対してパターンマッチさせる」ためのオプションです。なので、gオプションを付けないと、1度パターンマッチした段階で処理が終了することはわかるのですが、それがどういう結果になるのがいまひとつわかりません。
そこで、本編で作成したURLを検索するプログラムを例に、正規表現パターンのgオプションをなしにして結果を見てみることにしましょう。
おっと、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.」と「/」がこれに当たります。
複数回マッチした文字列のうち、最後にマッチした文字列が配列に格納されて返されます(次図を参照してみてください)。
ちなみに、先のmatch()メソッドの場合と同じようなやり方でexec()メソッドを実行してみると、次のようになります。
実行した結果、検索されたのは最初にパターンマッチしたURLだけです。このあとの表示も含めて、gオプションなしでmatch()メソッドを実行したときと、まったく同じ結果になっています。
実は「賢い」exec()メソッド
「ということで、exec()メソッドで検索する場合は、最後にパターンマッチするまで繰り返し実行しないと、マッチしたすべての文字列を取り出すことができないことがわかりました」
「でも、exec()メソッドを繰り返し実行しても、結局は最初にマッチした文字列を返すだけの繰り返しになるんじゃないですか?」
「実はですね、exec()メソッドは『マッチした文字列の位置を記憶する機能』を持っているのです。exec()メソッドの機能というよりは、RegExpオブジェクトの機能なのですが、繰り返し処理の中で実行した場合、2回目の実行の際に『前回マッチした文字列のあとの位置から検索を開始』します」
「『検索結果を1つしか返さない』というのは欠点のようにも思えましたが、実はこんな機能があったのですね」
「ですので、exec()メソッドは文字列を検索するだけでなく、繰り返し中で検索した文字列に対して何らかの処理も加えたいときにとても便利なのです」
while文でexec()メソッドを繰り返し実行する
「exec()メソッドが前回パターンマッチした位置(の最後)を記憶するのはわかりましたが、これ以上パターンマッチしないときはどうなるんです?」
「exec()メソッドは、これ以上パターンマッチする文字列がない場合はnullを返してきます。ですので、繰り返し処理を行う場合は、nullが返ってきた時点で処理を終了すればよいことになります」
「このような処理には、while文が適していますよね」
「では、先ほどのプログラムをwhile文に書き換えたパターンを作ってみますね。せっかくですので何か1つ処理を加えることにしましょう。exec()メソッドは、マッチした文字列とその他の情報を配列で返しますが、このときArrayオブジェクトのインスタンスに対しても情報を書き込みます。具体的には、検索結果に基づいてArrayオブジェクトの以下のプロパティの値を設定するんです」
プロパティ | 説明 | |
---|---|---|
input | パターンマッチに使用したパターン文字列を参照します。 | |
index | パターンマッチした位置を示す0から始まるインデックスを参照します。 |
「マッチした文字列の抽出に加えて、inputプロパティを参照することでマッチした位置を示すインデックスを取り出して、『○○番目の文字がマッチ』のように書き出すには、こんなふうになります」
「パターンマッチした文字列をすべて取得することに加えて、何かの処理を付け加えたいときにexec()メソッドを使うといいわけですね」
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- JavaScriptプログラミングをdocument.writeやalertで始める際の基礎知識をパーフェクトに解説する
初めてJavaScriptのWebアプリを作ってみたいという人に向けて「Hello World!」などの文字列を表示する方法について解説する。 - JavaScriptを中心としたWebアプリ開発の栄枯盛衰まとめ――LiveScriptからAngularJS/React.jsまで
@ITが誕生した2000年頃はJavaScriptが不遇だった時代。そこから現在のような人気のプログラミング言語になるまでには、どのような歴史があったのか。15周年を迎えた@ITの豊富なWeb開発関連記事とともに振り返る。 - ようこそJavaScriptの世界へ
JavaScriptで本格的なプログラミングの世界に触れてみよう。連載を通じて実用的なアプリケーションを作れるようになるはず!?(編集部)