JavaScript/RegExp
- JavaScript > RegExpオブジェクト
RegExp
[編集]RegExpオブジェクトは正規表現を扱うための標準組み込みオブジェクトである。
正規表現とは、文字列の検索や置換に用いられる文字規則の表現である。 JavaScriptは高度な正規表現の機能を備えている。
正規表現は、Unixのgrepやsedで文字列の検索の機能として採用される。その後awkという言語がそれに続き、Perlがその文法を受けついだ。 正規表現は言語ごとに機能の違いがあり、言語間の移植にあたっては注意を払う必要がある。
次にHTMLの要素名を取得する例を示す。要素名は"<"の文字に続く「先頭が英字でそれに0文字以上の英数字が続く文字列」である。これを正規表現で検索するには、以下のように記述する。
/<[a-zA-Z][a-zA-Z0-9]*/
これでHTMLの要素名を取得するには完全ではないのだが、とりあえずその点を飛ばして解説をする。 JavaScriptでは、正規表現をスラッシュ"/"の間に記述をする。 この規則の場合は小なり記号"<"に続き「 先頭が英字 で それに続き英数字が0文字以上(*)続く」ものがが要素名であるとすることでタグを検索している。
スラッシュで囲う表記法はJavaScriptで用意されている正規表現のリテラル表記で、実際には次の3つは意味的に等価である。
const regexp = /ab/;
const regexp = new RegExp( "ab" );
const regexp = new RegExp( /ab/ );
正規表現の作り方
[編集]正規表現には、前述した「*」以外にも様々な特殊記号が存在している。 まずはそれらを一覧する。
クエスチョン『?』
[編集]直前のパターンが存在しなくてもいいような場合を表す。
/html?/
はhtmlとhtmいずれにもマッチする。
プラス『*』
[編集]直前のパターンを0回以上繰り返した文字列を表す。
"Yaho*
"と表記すると、"Yahoo"や"Yahooooooo"、"Yah"にマッチする。
プラス『+』
[編集]直前のパターンを1回以上繰り返した文字列を返す。
「Go+gle
」と表記すると"Google"、"Goooooogle"でもマッチするが"Ggle"ではマッチしない点がアスタリスクでの表記と異なる。
中括弧『{n}』
[編集]n回繰り返したパターンを表す。 "{n,m}"ではn回以上、m回以下にマッチし"{n,}"でn回以上にマッチする。
例を挙げる。次の例は"Google"や"Goooooogle"にはマッチするが、"Gogle"にはマッチしない。
/Go{2,}gle/;
"*", "+", "?", "{n}", "{n,}", "{n,m}" 等のパターンのマッチ回数を表す文字を量指定子と言う。
ドット『.』
[編集]改行以外の任意の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]
では大文字のアルファベット以外を意味する。
半角スペース『 』
[編集]1文字分のスペースを表す。
バックスラッシュ『\』
[編集]直後の1文字の特殊文字をエスケープする。\|
とすると"|"という文字を表す
その他の特殊文字
[編集]JavaScriptでは次のような特殊文字も用意している。 これらはPerlで拡張された正規表現から受け継いでいる。
特殊文字 | 結果 |
---|---|
\t | 1文字分のタブを表す。 |
\f | フォームフィールドを表す。 |
\r | キャリッジリターンを表す。 |
\n | 改行記号を表す。 |
[\b] | バックスペースを表す。 |
\d | 1文字分の数字を表す。"[0-9]"に等しい |
\D | 数字以外の1文字を表す。"[^\d]"に等しい |
\w | 数字とアルファベットかアンダースコア(_)のいずれかを表す。"[0-9a-zA-Z_] "と等しい。 |
\W | \w以外の1文字を表す。"[^\w] "と等しい。 |
\s | 空白改行を表す。"[\t\n\v\f\r \u00a0\u2000-\u200b\u2028-\u3000]"と等しい。 |
\S | \s以外の1文字を表す。"[^\s]"と等しい。 |
\b | 単語の境界を表す。 |
\B | 単語がそこで終わらないことを意味する。 |
\b,\B のみ新しい概念なので解説する。
/alpha\b/;
の場合、"alpha beta"にはマッチするが、"alphabet"にはマッチしない。 "\B"はその逆で"alphabet"にはマッチするが、"alpha beta"にはマッチしない。
オプション
[編集]文字列"abrakadabra"に2箇所存在する"ab"の検索を考える。オプションを指定せずに検索を行うと最初の"ab"にはマッチするが、次の"ab"にマッチをしない。 全てにマッチするには、正規表現のオプションを利用して次のように表記する。
/ab/g
最後についているgがオプションで、globalを表す。実行結果は次のようになる。
const 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中のタグを取得する
const s="bbb<em>aaaa</em>ccc";
const m = s.match(/<.+?>(.*?)<\/.+?>/);
m[0]; // <em>aaaa</em> が返る。
m[1]; // aaaa が返る。
1、2、3とマッチした文字列が括弧の順に格納されている。 インデックスの0はマッチした文字列全体が格納されている。
後方参照の必要がない場合には、括弧の内部に"?:"を挿入して次の様に記述する。
/(?:abc)+/;
$1~$9
[編集]正規表現を実行して、マッチした結果を返す。
// i,b,big等のタグをemタグへ変換する
s.replace( /(<\/?)(?:i|b|s|small|strike|big|tt)/i, '$1em' ); // $1で参照結果("<"か"</")を呼び出し
先読み
[編集]Disjunction一致部分は結果に含まれない。
パターン | 説明 |
---|---|
(?=Disjunction) | 先読み言明(Lookahead assertions)。パターンDisjunctionが後に続くことが必要。 |
(?!Disjunction) | 否定先読み言明。パターンDisjunctionが後に続かないことが必要。 |
プロパティ
[編集]source
[編集]与えられた正規表現を返す。
console.log( new RegExp( "<.+?>", "gim" ).source ); // 『<.+?>』が表示される
global
[編集]正規表現にglobalオプション("g"のこと)が付いているかを返す。
(/ab/g).global; // trueが返る
(/ab/).global; // falseが返る
const rx = /ab/;
rx.global = true; // このようにしても値の設定は出来ないので注意
ignoreCase
[編集]正規表現にignoreCaseオプション("i"のこと)が付いているかを返す。
(/ab/ig).ignoreCase; // trueが返る
multiline
[編集]正規表現にmultilineオプション("m"のこと)が付いているかを返す。
(/ab/im).multiline; // trueが返る
lastIndex
[編集]文字列中で正規表現に最後にマッチした位置を返す。
const rx=/br/g;
rx.test("abracadabra");
rx.lastIndex; // 3が返る
const rx=/br/g;
rx.lastIndex = 10;
rx.test("abracadabra"); // 11文字中、10文字目からの検索のため結果はマッチせずfalseが返る
インスタンスメソッド
[編集]RegExp.prototype.exec(string)
[編集]引数で与えた文字列に正規表現を実行して、その結果を返す。 マッチする正規表現がなかった場合にはnullを返す。
const s = "abracadabra",
regex = /a./g;
let ary = null;
while (ary = regex.exec(s)) {
console.log(`${ary[0]} がマッチ、次のインデクスは ${regex.lastIndex}。`);
}
// ab がマッチ、次のインデクスは 2。
// ac がマッチ、次のインデクスは 5。
// ad がマッチ、次のインデクスは 7。
// ab がマッチ、次のインデクスは 9。
RegExp.prototype.test(string)
[編集]指定された正規表現を実行して、マッチする文字があったかどうかを真偽値型で返す。
const s = "abracadabra";
if (/ab/g.test(s)){
// ここから実際の処理
}
RegExp.prototype.toString()
[編集]作成した正規表現をオプション付きで返す。
console.log(new RegExp( "ab", "ig" ).toString()); // 「/ab/gi」が表示される