第1章 JavaScript導入ガイド

正規表現

2017年8月7日

正規表現の概要

正規表現は、文字列の中から特定のパターンにマッチする文字や記号を見つけることができます。

正規表現の基本的な使用方法

正規表現はマッチさせたいパターンをスラッシュで囲みます。

var re = /abcde/;

/abcde/ というパターンは、対象の文字列に abc という文字があるときだけマッチします。このように単純なパターンではなく、例えば a で始まって途中は何があるかわからないが最後が e という文字列を表したい場合、メタ文字を使います。

var re = /a.*e/;

上記で使っているドット( . )は改行以外の1文字を表し、アスタリスク( * )はその任意の文字の0回以上の繰り返しを意味しています。このように、正規表現において特殊な働きを持った文字を正規表現演算子、またはメタ文字と呼びます。
この正規表現リテラルはスクリプトの読み込み時に評価されます。

スクリプトの読み込み時ではなく、実行時に正規表現を評価したい場合などではRegExpを使います。RegExpのときはダブルクォーテーションでパターンを囲みます。

var re = new RegEXP("a.*e");

RegExpは実行時に正規表現を評価するので、パターンがかわる場合や、変数を使う場合などに使います。

match()

match()関数は指定した文字・正規表現にマッチする文字列を返します。

構文

str.match( パターン );

match関数は引数として渡したパターンにマッチする文字列を配列にして返します。

var str		= "ABCDEFG";
var re		= /A.*E/;
var found	= str.match(re);
console.log( found[0] );

ABCDE

次のように正規表現を直接引数として渡すこともできます。

var found	= str.match(/a.*e/);

複数マッチする g オプションを使うと、マッチしたすべての文字が配列で返されます。

var str	= "ABCDEFG";
var ret	= str.match( /./g );
console.log( ret );

["A", "B", "C", "D"]

返す値の特定の要素だけ欲しい場合、match()の後でインデックスを指定することで取得可能です。

var str	= "ABCDEFG";
console.log( str.match( /./g )[0] );

A

正規表現のメタ文字

正規表現で特に重要なのがメタ文字です。正規表現のメタ文字はその文字自体を表すものではありません。メタ文字を使うと、「行頭にあるパターンだけを探す」、「英数字を探す」、「大文字または小文字で始まるパターンだけを探す」など、さまざまな方法で検索パターンを指定することができます。

メタ文字の逆の意味を持つのがリテラルで、正規表現で特殊な意味がなく、表記どおりの文字列として扱われます。

文字クラス

ブラケット( [] )で囲んだ1つ以上のリテラル文字は文字の集合を表し、文字クラスと呼ばれます。文字クラスをパターンに使うと、複数の文字が含まれる場合はそのどれか1文字に当てはまる文字があればマッチします。

// a b c d e のどれか1文字を表現します
/[abcde]/
文字クラスの中では、ドット ( . ) やアスタリスク ( * )といったメタ文字は普通のリテラルとして扱われるので、エスケープ不要です。 // ドット1文字にマッチします /[.]/

文字や数字の範囲を示したいときはハイフン( - )が使えます。

// 数字1文字とマッチ
/[0-9]/
// 大文字・小文字を含めた英字1文字とマッチ
/[a-zA-Z]/ 

^ は否定を意味し、例えば下記は1、2、3のいずれでもない文字で始まるパターンにマッチします。

/[^123]/

文字集合の中に、ハイフン( - )など特殊文字そのものを含めたい場合は、その前にバックスラッシュ( / )をおいてエスケープします。

// zの後のハイフンは特殊文字ではなく通常の文字として使われます
/[a-z\-]/
正規表現の文字クラス
メタ文字 説明
[X]

ブラケット( [ ] )の中の任意の1文字にマッチします。

文字の間にハイフン( - )を挟み、文字列の範囲を表すことができます。たとえば、[12345]の様に規則的に連続した文字列は、[1-5] と表記できます。[abcd] は [a-d] と表記できます。

下記はgオプションを使ってマッチする文字がなくなるまで繰り返しています。

var str	= "A-B-C";
console.log( str.match( /[a-zA-Z0-9]/g ) );

["A", "B", "C"]

[^X]

ブラケット( [ ] )の中に含まれない任意の1文字にマッチします。
それ以外は[X]と同じです。

var str	= "A-B-C";
console.log( str.match( /[^a-zA-Z0-9]/g ) );

["-", "-"]

\w

アンダースコアを含む英数字の1文字にマッチします。
[a-zA-Z_0-9] と同じです。

var str	= "You talkin' to me?";
console.log( str.match( /\w/g ) );

["Y", "o", "u", "t", "a", "l", "k", "i", "n", "t", "o", "m", "e"]

\W

アンダースコアを含む英数字以外の1文字にマッチします。
[^a-zA-Z_0-9] と同じです。

var str	= "You talkin' to me?";
console.log( str.match( /\W/g ) );

[" ", "'", " ", " ", "?"]

\d

数字の1文字にマッチします。
[0-9] と同じです。

var str	= "The Magnificent 7";
console.log( str.match( /\d/g ) );

["7"]

\D

数字以外の1文字にマッチします。
[^0-9] と同じです。

var str	= "The Magnificent 7";
console.log( str.match( /\D/g ) );

["T", "h", "e", " ", "M", "a", "g", "n", "i", "f", "i", "c", "e", "n", "t", " "]

\s

空白文字にマッチします。
空白文字にはスペース、タブ、改行などが含まれます。

var str	= "The Magnificent 7";
console.log( str.match( /\s/g ) );

[" ", " "]

\S

空白文字以外にマッチします。

var str	= "The Magnificent 7";
console.log( str.match( /\S/g ) );

["T", "h", "e", "M", "a", "g", "n", "i", "f", "i", "c", "e", "n", "t", "7"]

[\b]

リテラルバックスペース(U+0008)にマッチします。
\b と混同しないように、ブラケットで囲みます。

選択・グループ化・参照

あとで使えるようにマッチした文字列を記録したり、複数のパターンのどちらかにマッチさせることができます。

正規表現の選択・グループ化・参照
正規表現の文字クラス
メタ文字 説明
(X)

カッコ( () )は、囲んだパターンにマッチした文字列を記録します。カッコで囲んだグループの左から順に、RegExp オブジェクトを使って RegExp.$1、RegExp.$2、RegExp.$3...という表記で参照できます。これを後方参照といいます。

var str	= "After all, tomorrow is another day.";
// 先頭の単語にマッチ
str.match( /^(\w+)/ ); 

console.log( RegExp.$1 );

After

後方参照は replace() の第2引数にも使えます。

var str	= "after all, tomorrow is another day.";
// 行頭の単語にを大文字に変換
console.log( str.replace( /^(\w)/, RegExp.$1.toUpperCase() ) ); 

After all, tomorrow is another day.

replace() 内であれば RegExp を省略できます。

var str	= "after all, tomorrow is another day.";
// 行頭の単語にを大文字に変換
console.log( str.replace( /^(\w)/, "($1)" ) ); 

(a)fter all, tomorrow is another day.

(?:X)

(X)と同じでカッコ内のパターンにマッチしますが、後方参照できません。

var str	= "After all, tomorrow is another day.";
// 先頭の単語にマッチ
str.match( /^(?:\w+)/ ); 

console.log( RegExp.$1 );

undefined

X|Y

| の前後あるどちらかの正規表現にマッチします。X|Y であれば X、Y のいずれか1つの文字にマッチします。
下記では g オプションを使ってどちらの選択もマッチするようにしています。

var str	= "Don’t think, feel.";

console.log( str.match( /think|feel/g ) ); 

["think", "feel"]

選択一致パターンとグループ化の組み合わせ

選択一致パターンの | は、文字列のグループ化と組み合わせて使うと効果的です。たとえば、What is your favorite? か What is your hobby? という文章を探したい場合は、次のように書くことができます。

/What is your (favorite|hobby)?/

ただ、グループ化すると自動的に後方参照用に記憶されるので、多少ではありますが処理が遅くなります。これを避けるには、後方参照を行わないグループ化の構文「(?:...)」を使います。

// マッチした文字列は記録されません
/What is your (?:favorite|hobby)?/

量指定子

量指定子は、その直前の要素が何回マッチするかを指定します。たとえば、a* は0個以上の a にマッチします。

正規表現の量指定子
メタ文字 説明
* 直前の文字の 0 回以上の繰り返しにマッチします。
+ 直前の文字の 1 回以上の繰り返しにマッチします。
? 直前の文字の 0 個か 1個にマッチします。
. 改行文字( ¥n )を除く任意の 1 文字にマッチします。
{m, n}

直前の文字が m 回以上、n 回以下の繰り返しにマッチします。

{m} m 回の繰り返しにマッチ {m,} m 回以上の繰り返しにマッチ {m,n} m 回以上、n 回以下の繰り返しにマッチ

a が少なくとも1回、最大でも3回繰り返すパターンを検索

/a{1,3}/

a が3回繰り返すパターンを検索

/a{3}/

a が少なくとも1回以上続くパターンを検索

/a{1,}/

貪欲量指定子

量指定子は可能な限り長いマッチを行います。次の例は、空白と任意の1文字の後に eed が続く単語を探したい場合の間違った例です。

var str	= "The need for speed!";

console.log( str.match( / .+eed/ )[0] ); 

need for speed

needにマッチすることを期待していましたが、.*は need for speed までマッチしてしまいます。量指定子は許された最大数マッチしようとするので、.* は1つ目の候補の need を過ぎて2つ目の候補の speed までマッチしてしまいました。

最短マッチを行いたい場合は、量指定子の後にクエスチョン( ? )を使います。

console.log( str.match( / .+?eed/ )[0] ); 

need

基本的な繰り返しパターン検索
// 0個、または1個以上の A にマッチ
/A?/

// 0個以上の A にマッチ
/A*/

// 1個以上の A にマッチ
/A+/ 

// 0個、または1個以上の任意の文字にマッチ
/.?/

// 0個以上の任意の文字にマッチ 
/.*/ 

// 1個以上の任意の文字にマッチ
/.+/ 

アンカー

アンカーは、行頭や行末など、文字列中の位置にマッチします。行頭を表す ^ と、行末を表す $はおぼえておいたほうがよいでしょう。

正規表現のアンカー
メタ文字 説明
^

先頭にマッチします。複数行検索になっている場合はすべての行の先頭にもマッチします。

var str	= "as soon as possible";
// 先頭の as しかマッチしない
console.log( str.match( /^as/g ) ); 

["as"]

ブラケットで囲まれた文字集合の中で使われたときは行頭ではなく否定のメタ文字として使われます。

$

末尾にマッチします。複数行検索になっている場合はすべての行の末尾にもマッチします。

var str	= "as soon as possible";
// 末尾の単語しかマッチし
console.log( str.match( /\w+$/g ) ); 

["possible"]

\b

単語の区切りにマッチします。単語に含まれるのは\w(英数字とアンダースコア)のみで、それ以外が単語の区切りと判断されます。

var str	= "The need for speed!";
console.log( str.match( /\bneed/ )[0] ); 

need

\b はマッチした文字に含まれないことに注意してください。\b にマッチした空白はマッチした文字に含まれません。

\B 単語の区切り以外の文字にマッチします。それ以外は \b と同じです。
X(?=Y)

X の後に Y が続く場合のみ X にマッチします。

var str	= "I'm the king of the world!";

console.log( str.match( /.*(?=of)/ )[0] ); 

I'm the king

X(?!Y)

X の後に Y が続かない場合のみ X にマッチします。

var str	= "I'm the king of the world!";

// 単語1文字以上と、単語以外にマッチ
console.log( str.match( /\w+(?!\w)/ )[0] );

I

正規表現のエスケープシーケンス

メタ文字をエスケープする

バックスラッシュ( \ ) を使って後続の文字をエスケープすると、メタ文字をリテラルとしてマッチさせることができます。

たとえば、ドメイン名には、メタ文字のドット( . )が含まれますが、エスケープを使わずにドットを使うと任意の1文字にマッチしてしまいます。

var str	= "rfs_jp";
console.log( str.match( /rfs.jp/ ) );

rfs_jp

エスケープすることで、ドット以外の文字にはマッチしなくなります。

console.log( str.match( /rfs\.jp/ ) );

null

正規表現では以下のエスケープシーケンスが使えます。

エスケープシーケンスの一覧
メタ文字 説明
\b バックスペース
\t 水平タブ
\v 垂直タブ
\n 改行
\r 行頭復帰
\f 改ページ
\' シングルクオーテーション
\" ダブルクオーテーション
バックスラッシュ
\0 NULL文字
\cX X で指定した制御文字にマッチします。X には A - Z のいずれかの 1 文字が入ります。
例えば、/\cM/ は、文字列中の control-M にマッチします。
\xXX 2桁の16進数からなる文字にマッチします。正規表現で ASCII コードを表現できます。
\uXXXX 4桁の16進数からなる文字にマッチします。正規表現で Unicodeを表現できます。

正規表現を扱うメソッド

replace()

replace() は、パターンにマッチした文字列を指定した文字で置き換えて、その結果の文字列を返します。指定した文字列を任意の文字列で変更することを置換と言います。

構文

str.replace( パターン, 置換文字 )

引数
パターン
文字列・正規表現を指定子ます。マッチした文字列は第1引数の置換文字と置き換えられます。
パターンには下記のオプションを指定できます。
オプション 効果
g 繰り返してマッチ。マッチする文字列がなくなるまで繰り返される。
i 英字の大文字、小文字を区別しない。
m 複数行に対応したマッチ。複数行で行頭( ^ )および行末( $ )が有効になる。

// 繰り返しマッチ、aからzまでの文字すべてにマッチします。
var str	= "abcDEfg";
console.log( str.match( /[a-z]/g ) );

["a", "b", "c", "f", "g"]

// aからzまでの大文字、小文字の文字すべてにマッチします。
var str	= "abcDEfg";
console.log( str.match( /[a-z]/ig ) );

["a", "b", "c", "D", "E", "f", "g"]

// 行頭の T にマッチ、複数行に対応します(getElementById でテキストエリアの文字を取得している前提)。
var str = document.getElementById("text");
console.log( str.match( /^T/m ) );
置換文字

第1引数でマッチした文字列を置き換える文字列、もしくは実行する関数を指定します。 第2引数に関数を指定している

var str	= "after all, tomorrow is another day.";
// 行頭の単語にを大文字に変換
console.log( str.replace( /^(\w)/, RegExp.$1.toUpperCase() ) ); 

After all, tomorrow is another day.

返却値
パターンにマッチした文字列を置換文字で置き換えた新しい文字列を返します。

search()

search() は指定した文字・正規表現にマッチする文字列を返します。

構文

str.search( パターン );

search() は、引数として渡したパターンにマッチマッチした場所のインデックスを返します。マッチしなかった場合は -1 を返します。

var str		= "abcDEFG";
console.log( str.search( /[A-Z]/ ) );

3

split()

split() は、指定した区切り文字で文字列を分割し、配列にして返します。

構文

str.split([区切り[, リミット]])

引数
区切り
文字列を区切るための文字を指定します。正規表現も使えます。
区切りに空文字を指定、もしくは省略した場合、文字ごとに分割されます。
リミット
分割数の制限を指定します。
返却値
分割後の配列です。
// カンマで分割
var str = "One,Two,Three";
console.log( str.split(",") );

["One", "Two", "Three"]

// 空白で分割
var str = "One Two Three";
console.log( str.split(/\s/) );

["One", "Two", "Three"]

// リミットを2に設定
var str = "One Two Three";
console.log( str.split(/\s/, 2) );

["One", "Two"]

test()

test() は、パターンにマッチしたかどうかを返します。マッチしたら true、マッチしなければ false を返します。文字列がパターンにマッチするかを判別したい場合は test()、マッチした文字列が必要な際は match() を使います。

構文

RegExpオブジェクト.test( 文字列 )

/[a-z]/.test("ABC");

false

/[a-z]/.test("abc");

true

正規表現のテクニック集

文字列の末尾が改行かをチェックする

改行コードはオペレーティングシステムによって違います。UNIX 系 OS の改行は \n、ウインドウズは \r\n 、マッキントッシュは \r が使われています。次のコードはどの環境の改行コードにもマッチします。

/[\r\n]/

ワード境界の罠

空白文字の集合を表す \s 、ワードの集合を現す \w 、ワードの境界を表す \b の組み合わせには十分な注意が必要です。

次の正規表現は、後ろに空白文字が続くワードを拾おうとしています。一見、まともな正規表現に見えますね。

/(\w+)\s+/;

「It is enjoy」というような文字列でしたら問題ないのですが、「It's enjoy」というようにワード以外を含んだ文字列にはマッチしません。「It's」のシングルクォートの箇所がワードの区切りとなり、空白文字の直前にある「s」しか取り出せません。正解は次のようになります。

/(\S+)\s+/;

このように、なるべく、\s の次には \S を続けるように注意しましょう。

マッチしないパターンを使わない

マッチしないパターンは、マッチするパターンより処理時間が何十倍もかかることがあります。これはマッチするパターンはマッチした時点でその処理を終わらせられますが、マッチしない場合は様々なケースでマッチしないことを確認する必要があるためです。

行末で分割する

行末は、OS (Unix、Windows など) により ¥r¥n や ¥r、¥n などの違いがあります。正規表現を使えば、どのOSでも改行毎の処理ができます。

var str		= 'One\nTwo\nThree';
var lines	= str.split(/\r\n|\r|\n/);
console.log(lines);

["One", "Two", "Three"]

Comment

コメントを残す

メールアドレスが公開されることはありません。

関連記事

リズムファクトリーはホームページの制作会社です。
ホームページ制作に関するご要望・ご相談はこちらからどうぞ。