JavaScript 標準ライブラリ RegExp
出典: フリー教科書『ウィキブックス(Wikibooks)』
- JavaScript > RegExpオブジェクト
目次 |
[編集] RegExp
正規表現とは、文字列の検索や置換に用いられる、文字の規則表現の方法である。 JavaScriptは文字列に執着があったのか、高度な正規表現の機能を備えている。 正規表現は、Unixの世界で、grepやsedで、文字列の検索の機能として採用され、その後awkという言語がそれに続き、Perlがその文法を受けついだ。 正規表現は、言語ごとに機能の違いがあり、汎用言語ではPerlが最も高機能だが、それぞれに気にかける程の差は無い。
例えばHTMLでの要素名を取得する際には、"<"の文字から始まり英数字が続くため、これを検索するには正規表現では次の様に記述する。
/<[a-zA-z]+/
これでHTMLの要素名を取得するには完全ではないのだが、とりあえずその点を飛ばして解説をする。 JavaScriptでは、正規表現をスラッシュ"/"の間に記述をする。 この規則の場合は小なり記号"<"に続いているA~Zの記号がタグであるとしてタグを検索できる。 続いている"+"の記号は1文字以上であると表している。
スラッシュで囲う表記法はJavaScriptで用意されているシンタックスシュガーで、実際には次の2つは意味的に等価である。
var regexp = new RegExp( "ab" ); var regexp = /ab/;
[編集] 正規表現の作り方
正規表現には、前述した「+」以外にも様々な特殊記号が存在している。 まずはそれらを一覧する。
[編集] アスタリスク『*』
直前の文字を0回以上繰り返した文字列を表す "Yaho*"と表記すると、"Yahoo"や"Yahooooooo"にマッチする。
[編集] プラス『+』
直前の文字を1回以上繰り返した文字列を返す 「Go+gle」と表記すると"Google"、"Goooooogle"でもマッチするが"Ggle"ではマッチしない点がアスタリスクでの表記と異なる。
[編集] クエスチョン『?』
直前の文字が存在しなくてもいいような場合を表す
html?
はhtmlとhtmいずれにもマッチする。
[編集] ドット『.』
改行以外の任意の1文字を表す。
[編集] 半角スペース『 』
1文字分のスペースを表す。
[編集] ハット記号『^』
行の先頭を表す。
[編集] ドル記号『$』
行末を表す。
[編集] フェンス『|』
指定したもののいずれか、を表す。
[編集] 括弧『()』
括弧の中の文字列を表す。フェンスと組み合わせて次の様に使用する。
(りんご|ゴリラ|ラッパ)
[編集] ブラケット『[]』
囲った範囲の文字のいずれかにマッチする場合を表す。 つまり次の2文は同じ意味を持つ。
/(0|1|2|3|4|5|6|7|8|9)/; /[0123456789]/;
[編集] ブラケット『[A-Z]』
A~Zまでの文字列のいずれかを表す 同様に"[a-z]"では小文字のa~zを、"[0-9]"では数字の0~9のいずれかを表す。 ちなみに、ブラケットとフェンスの組み合わせは組み合わせることが出来るため、 "[0-9a-zA-Z_]"とすれば、数字かアルファベット、アンダーバーのいずれかにマッチする。
[編集] 否定演算子『^』
ブラケットの中で使用し、指定した文字以外を意味する。 "[^A-Z]"では大文字のアルファベット以外を意味する。
[編集] 中括弧『{n}』
n回繰り返した文字列を表す。 "{n,m}"ではn回以上、m回以下にマッチし"{n,}"でn回以上にマッチする。
例を挙げる。次の例は"Google"や"Goooooogle"にはマッチするが、"Gogle"にはマッチしない。
/Go{2,}gle/;
[編集] 円記号『\』
直前の1文字の正規表現の意味をエスケープする。 上述したブラケット"["やフェンス"|"の意味をエスケープする。
"*","+","?","{n}","{n,}","{n,m}"等の文字のマッチ回数を表す文字を量指定子と言う。
[編集] メタシンボル
この様に、量指定子で指定できる文字をメタシンボルと言うが、JavaScriptでは次の様なメタシンボルも用意している。 これらの全てはPerlで拡張された正規表現から受け継いでいる。
| メタシンボル | 結果 |
|---|---|
| \d | 1文字分の数字を表す。"[0-9]"に等しい |
| \D | 数字以外の1文字を表す。"[^0-9]"に等しい |
| \t | 1文字分のタブを表す。 |
| \f | フォームフィールドを表す。 |
| \r | キャリッジリターンを表す。 |
| \n | 改行記号を表す。 |
| \s | \b,\t,\f,\r,\nのいずれかを表す。"[\b\t\f\r\n]"と等しい。 |
| \b | 単語とスペースの境界を表す |
| \B | 単語がそこで終らないことを意味する。 |
| \S | \b,\t,\f,\r,\n以外の1文字を表す。"[^\b\t\f\r\n]"と等しい。 |
| \w | 数字とアルファベットかアンダースコア(_)のいずれかを表す。"[0-9a-zA-Z_] "と等しい。 |
\b,\B のみ新しい概念なので解説する。
/alpha\b/;
の場合、"alpha beta"にはマッチするが、"alphabet"にはマッチしない。 "\B"は其の逆で"alphabet"にはマッチするが、"alpha beta"にはマッチしない。
[編集] オプション
紹介したようにJavaScriptには強力な検索機能があるがまだ問題がある。 文字列"abrakadabra"には"ab"が2箇所存在するが、正規表現で検索を行うと最初の"ab"にはマッチするが、次の"ab"にマッチをしない。 これを解決するには正規表現のオプションを活用して次の様に表記する。
/ab/g
最後についているgがオプションで、globalを表す。実行結果は次の様になる。
var s = "abrakadabra"; s = s.replace( /ab/g, '**' ); // **rakad**ra
その他にも、さまざまなオプションが存在するが、組み合わせて利用する場合には連続して記述をすればよい。
/ab/g; /ab/igm; // i,g,mの3オプション new RegExp( "ab", "i" ); new RegExp( "ab", "gm" );
それぞれのオプションの意味は次の通りである。
| オプション | 説明 |
|---|---|
| g | 全文検索を行う。 |
| i | 大文字、小文字の区別無くマッチする。 |
| m | 複数行のマッチに対応する。 |
[編集] 貪欲なマッチ
正規表現は基本的にマッチする限り一番長い組み合わせを取得しようとする。これを最長マッチ(貪欲なマッチ)と言う。 これは「\w+」としてマッチする限り文字を拾い続ければ単語が取得できる事からも自然な仕様と言えるが、「<.+>」の様に記述した場合には、HTMLのタグ一つではなく、文中の一番長い"<"と">"の間を取得する。 これを抑制するためには、量指定子(quantifier)である"+"に続いて"?"を付ける事で、最も短い組み合わせを取得できる。これを最短マッチと言う。
[編集] 後方参照
正規表現中で括弧「()」を使用して囲った文字列は、後方参照の対象となる。 マッチした文字列は、保存されて後に取得が可能である。
// HTML中のタグを取得する var s="bbb<em>aaaa</em>ccc"; var m = s.match(/(<.+?>.*?<\/.+?>)/); m[1]; // <em>aaaa</em> が返る。
1、2、3とマッチした文字列が括弧の順に格納されている。 インデックスの0はマッチした文字列全体が格納されている。
後方参照を行いたくない場合には括弧の内部に"?:"を挿入して次の様に記述する。
/(?:<.+?>.*?<\/.+?>)/;
| パターン | 説明 |
|---|---|
| (?:Disjunction) | グループ化のみで一致した文字列を記憶しない。 |
| (?=Disjunction) | 先読み言明(Lookahead assertions)。後に続くパターンDisjunctionに続く事が必要条件。ただし、Disjunction一致部分は結果に含まれない。 |
| (?!Disjunction) | 否定先読み言明。後に続く文字がDisjunctionに一致しないことが必要条件。 |
[編集] プロパティ
[編集] $1~$9
正規表現を実行して、マッチした結果を返す。
// i,b,big等の廃止予定要素をemタグへ変換する
s.replace( /(<\/?)(i|b|s|small|strike|big|tt)/i, '$1em' ); // $1で参照結果("<"か"</")を呼び出し
また、次の様な使い方も出来る。
var m = "aaa[em]bbb[/em]ccc[p]ddd[/p]".match(/(\[.+?\]).+?(\[.+?\])/g); document.write( RegExp.$1 ); // [em] が表示される document.write( RegExp.$2 ); // [/em] が表示される
このとき参照に使っている。RegExpはプログラム実行時に用意されている特別な変数である。 これは、Perlで正規表現の実行結果をグローバルな特殊変数に自動保存される仕掛けを踏襲している。
[編集] source
与えられた正規表現を返す。
document.write( new RegExp( "<.+?>", "gim" ).source ); // 『<.+?>』が表示される
[編集] global
正規表現にglobalオプション("g"のこと)が付いているかを返す。
(/ab/g).global; // trueが返る (/ab/).global; // falseが返る var rx = (/ab/); rx.global = true; // この様にしても値の設定は出来ないので注意
[編集] ignoreCase
正規表現にignoreCaseオプション("i"のこと)が付いているかを返す。
(/ab/ig).ignoreCase; // trueが返る
[編集] multiline
正規表現にmultilineオプション("m"のこと)が付いているかを返す。
(/ab/im).multiline; // trueが返る
[編集] lastIndex
文字列中で正規表現に最後にマッチした位置を返す。
var rx=/br/g;
rx.test("abracadabra");
rx.lastIndex; // 3が返る
var rx=/br/g;
rx.lastIndex = 10;
rx.test("abracadabra"); // 11文字中。10文字目からの検索のため結果はマッチせずfalsezが返る
[編集] メソッド
[編集] exec(string)
引数で与えた文字列に正規表現を実行して、その結果を返す。 マッチする正規表現がなかった場合にはnullを返す。 これは、Stringオブジェクトのmatchとほぼ等価の構文である。 つまりは次の2文はほぼ等価である。
// var s = "abracadabra"; が既に宣言されている var m = s.match(/ab/g); var m = (/ab/g).exec(s);
[編集] test(string)
指定された正規表現を実行して、マッチする文字があったかどうかを真偽値型で返す。
var s="abracadabra";
if( (/ab/g).test( s ) ){
// ここから実際の処理
}
[編集] toString()
作成した正規表現をオプション付きで返す。
document.write( new RegExp( "ab", "g" ).toString() ); // 「/ab/g」が表示される