RegExp オブジェクト

RegExp オブジェクトは正規表現機能を提供します。

概要

正規表現 (正規表現) は、テキスト パターン (つまり、文字列構造) を表現する方法であり、文字列のテンプレートに似ており、「指定されたパターン」に従ってテキストを照合するためによく使用されます。たとえば、正規表現は電子メール アドレスのパターンを与え、それを使用して文字列が電子メール アドレスであるかどうかを判断します。 JavaScript の正規表現システムは Perl 5 に基づいています。

新しい正規表現を作成するには 2 つの方法があります。 1 つは、スラッシュで始まりスラッシュで終わるリテラルを使用することです。

var regex = /xyz/;

もう 1 つは、RegExp コンストラクターを使用する方法です。

var regex = 新しい RegExp('xyz');

上記の 2 つの記述方法は同等であり、どちらも内容 xyz を持つ新しい正規表現オブジェクトを作成します。これらの主な違いは、最初のメソッドはエンジンがコードをコンパイルするときに新しい正規表現を作成し、2 番目のメソッドは実行時に新しい正規表現を作成するため、前者の方が効率的であることです。さらに、前者の方が便利で直感的であるため、実際のアプリケーションでは、基本的に正規表現の定義にリテラルが使用されます。

RegExp コンストラクターは、修飾子を表す 2 番目のパラメーターも受け入れることができます (詳細は以下で説明します)。

var regex = new RegExp('xyz', 'i');
// と同等
var regex = /xyz/i;

上記のコードでは、正規表現 /xyz/ に修飾子 i が付いています。

##インスタンスのプロパティ

通常のオブジェクトのインスタンス プロパティは 2 つのカテゴリに分類されます。

1 つのタイプはモディファイアに関連しており、どのモディファイアが設定されているかを理解するために使用されます。

  • RegExp.prototype.ignoreCase: i 修飾子が設定されているかどうかを示すブール値を返します。
  • RegExp.prototype.global: g 修飾子が設定されているかどうかを示すブール値を返します。
  • RegExp.prototype.multiline: m 修飾子が設定されているかどうかを示すブール値を返します。
  • RegExp.prototype.flags: 設定されているすべての修飾子を含む文字列をアルファベット順に返します。

上記 4 つのプロパティはすべて読み取り専用です。

var r = /abc/igm;

r.ignoreCase // true
r.global // true
r.multiline // true
r.flags // 'ギム'

もう 1 つは修飾子とは関係のない属性で、主に次の 2 つです。

  • RegExp.prototype.lastIndex: 次の検索が開始される位置を示す整数を返します。この属性は読み取りおよび書き込み可能ですが、継続的な検索を実行する場合にのみ意味を持ちます。詳細については、次の記事を参照してください。
  • RegExp.prototype.source: 正規表現の文字列形式 (バックスラッシュを除く) を返します。このプロパティは読み取り専用です。
var r = /abc/igm;

r.lastIndex // 0
r.source // "abc"

##インスタンスメソッド

RegExp.prototype.test()

通常のインスタンス オブジェクトの test メソッドは、現在のパターンがパラメータ文字列と一致するかどうかを示すブール値を返します。

/cat/.test('猫と犬') // true

上記のコードはパラメータ文字列に cat が含まれているかどうかを検証し、結果は true を返します。

正規表現に g 修飾子がある場合、各 test メソッドは最後の終了位置から逆方向に照合を開始します。

var r = /x/g;
var s = '_x_x';

r.lastIndex // 0
r.test(s) // true

r.lastIndex // 2
r.test(s) // true

r.lastIndex // 4
r.test(s) // false

上記のコードの正規表現では「g」修飾子が使用されています。これは、グローバル検索であり、複数の結果が存在することを意味します。次に、「test」メソッドを 3 回使用します。毎回の検索開始位置は、前回の一致の後の位置です。

g 修飾子を使用すると、通常のオブジェクトの lastIndex プロパティを通じて検索を開始する位置を指定できます。

var r = /x/g;
var s = '_x_x';

r.lastIndex = 4;
r.test(s) // false

r.lastIndex // 0
r.test(s) // true

上記のコードは、文字列の 5 番目の位置から検索を開始することを指定しています。この位置は空であるため、「false」が返されます。同時に、「lastIndex」プロパティは「0」にリセットされるため、「r.test(s)」の 2 回目の実行では「true」が返されます。

g 修飾子が使用される場合、最後の lastIndex 属性が正規表現の内部で記憶されることに注意してください。この時点で、一致する文字列は変更されるべきではありません。そうしないと、いくつかの微妙なエラーが発生します。

var r = /bb/g;
r.test('bb') // true
r.test('-bb-') // false

上記のコードでは、正規表現 r が最後の lastIndex 位置から照合を開始するため、test メソッドが 2 回目に実行されるときに予期しない結果が発生します。

lastIndex 属性は同じ正規表現に対してのみ有効であるため、次のような書き方は誤りです。

変数カウント = 0;
while (/a/g.test('babaa')) count++;

上記のコードは無限ループを引き起こします。これは、「while」ループの各一致条件が新しい正規表現であり、「lastIndex」属性が常に 0 に等しくなるためです。

通常のパターンが空の文字列の場合、すべての文字列が一致します。

新しい RegExp('').test('abc')
// 真実

RegExp.prototype.exec()

通常のインスタンス オブジェクトの exec() メソッドは、一致する結果を返すために使用されます。一致が見つかった場合は、正常に一致した部分文字列をメンバーとする配列が返されます。それ以外の場合は、「null」が返されます。

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

上記のコードでは、通常のオブジェクト r1 が一致した場合は配列が返され、通常のオブジェクト r2 が一致しなかった場合は null が返されます。

正規表現に括弧が含まれている場合 (つまり、「グループ一致」が含まれている場合)、返される配列には複数のメンバーが含まれます。最初のメンバーは成功した一致全体の結果であり、後続のメンバーは括弧に対応する一致したグループです。つまり、第 2 メンバーは第 1 ブラケットに対応し、第 3 メンバーは第 2 ブラケットに対応し、以下同様になります。配列全体の「length」プロパティは、一致するグループの数に 1 を加えたものと等しくなります。

var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]

上記のコードの exec() メソッドは配列を返します。最初のメンバーは一致全体の結果であり、2 番目のメンバーは括弧内の一致の結果です。

exec() メソッドの戻り配列には、次の 2 つのプロパティも含まれます。

  • input: 元の文字列全体。
  • index: 成功したパターン マッチングの開始位置 (0 から数えます)。
var r = /a(b+)a/;
var arr = r.exec('_abbba_aba_');

arr // ["abbba", "bbb"]

arr.index // 1
arr.input // "_abbba_aba_"

一致は元の文字列の 2 番目の位置から開始されるため、上記のコードの index 属性は 1 に等しくなります。

正規表現に g 修飾子を追加すると、exec() メソッドを複数回使用でき、次の検索位置は前回の一致が正常に終了した位置から開始されます。

var reg = /a/g;
var str = 'abc_abc_abc'

var r1 = reg.exec(str);
r1 // ["a"]
r1.index // 0
reg.lastIndex // 1

var r2 = reg.exec(str);
r2 // ["a"]
r2.index // 4
reg.lastIndex // 5

var r3 = reg.exec(str);
r3 // ["a"]
r3.index // 8
reg.lastIndex // 9

var r4 = reg.exec(str);
r4 // null
reg.lastIndex // 0

上記のコードは、「exec()」メソッドを連続して 4 回使用しています。最初の 3 回は、前の一致の最後から後方に一致します。 3 番目の一致が終了すると、文字列全体が最後に達し、一致結果は null を返し、通常のインスタンス オブジェクトの lastIndex 属性も 0 にリセットされます。これは、4 番目の一致が開始されることを意味します。始まり。

複数の一致を許可する「g」修飾子の機能を利用して、すべての一致を 1 つのループで完了できます。

var reg = /a/g;
var str = 'abc_abc_abc'

while(true) {
  var match = reg.exec(str);
  if (!match) ブレーク;
  console.log('#' + match.index + ':' + match[0]);
}
// #0:a
// #4:a
// #8:a

上記のコードでは、exec() メソッドが null を返さない限り、ループは継続し、毎回一致する位置と一致するテキストを出力します。

通常のインスタンス オブジェクトの lastIndex プロパティは、読み取りだけでなく書き込みも可能です。 g 修飾子が設定されている場合、lastIndex の値が手動で設定されている限り、指定された位置からマッチングが開始されます。

文字列インスタンスメソッド

文字列のインスタンスメソッドのうち正規表現に関係するものが4つあります。

  • String.prototype.match(): メンバーがすべて一致する部分文字列である配列を返します。
  • String.prototype.search(): 指定された正規表現に従って検索し、一致の開始位置を示す整数を返します。
  • String.prototype.replace(): 指定された正規表現に従って置換し、置換された文字列を返します。
  • String.prototype.split(): 指定されたルールに従って文字列を分割し、分割されたメンバーを含む配列を返します。

String.prototype.match()

文字列インスタンス オブジェクトの match メソッドは、文字列に対して通常のマッチングを実行し、マッチング結果を返します。

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

s.match(r1) // ["x"]
s.match(r2) // null

上記のコードからわかるように、文字列の match メソッドは通常のオブジェクトの exec メソッドと非常によく似ています。一致が成功した場合は配列が返され、一致した場合は null が返されます。失敗します。

正規表現に g 修飾子がある場合、このメソッドは正規表現の exec メソッドとは異なる動作をし、すべての一致する結果を一度に返します。

vars = 'アバ';
var r = /a/g;

s.match(r) // ["a", "a"]
r.exec(s) // ["a"]

正規表現の lastIndex 属性を設定しても、一致は常に文字列の最初の文字から開始されます。

var r = /a|b/g;
r.lastIndex = 7;
'xaxb'.match(r) // ['a', 'b']
r.lastIndex // 0

上記のコードは、通常のオブジェクトの lastIndex プロパティの設定が無効であることを示しています。

String.prototype.search()

文字列オブジェクトの search メソッドは、文字列全体の中で条件を満たす最初の一致結果の位置を返します。一致するものがない場合は -1 が返されます。

'_x_x'.search(/x/)
// 1

上記のコードでは、最初に一致した結果は文字列の '1' の位置に表示されます。

String.prototype.replace()

文字列オブジェクトの「replace」メソッドは、一致する値を置き換えることができます。 2 つのパラメータを受け入れます。1 つ目は検索パターンを示す正規表現で、2 つ目は置換コンテンツです。

str.replace(検索、置換)

正規表現に「g」修飾子が追加されていない場合は、最初に一致した値が置換され、それ以外の場合は、一致した値がすべて置換されます。

'aaa'.replace('a', 'b') // "ばあ"
'aaa'.replace(/a/, 'b') // "ばあ"
'aaa'.replace(/a/g, 'b') // "bbb"

上記のコードでは、最後の正規表現で「g」修飾子が使用されており、すべての「a」が置き換えられます。

「replace」メソッドの応用例の 1 つは、文字列の先頭と末尾のスペースを削除することです。

var str = ' #id div.class ';

str.replace(/^\s+|\s+$/g, '')
// "#id div.class"

「replace」メソッドの 2 番目のパラメータでは、ドル記号「$」を使用して、置換されるコンテンツを参照できます。

  • $&: 一致した部分文字列。
  • $`: 結果の前のテキストと一致します。
  • $': 結果の後のテキストと一致します。
  • $n: 一致に成功したコンテンツの n 番目のグループ。 n は 1 から始まる自然数です。
  • $$: ドル記号 $ を指します。
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// 「世界こんにちは」

'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"

上記のコードでは、最初の例は一致するグループの位置を交換することであり、2 番目の例は一致する値を書き換えることです。

「replace」メソッドの 2 番目のパラメータは、一致する各コンテンツを関数の戻り値で置き換える関数にすることもできます。

'3 と 5'.replace(/[0-9]+/g, function (match) {
  2 * 一致を返します。
})
// 「6と10」

var a = '機敏な茶色のキツネは怠惰な犬を飛び越えました。';
var pattern = /quick|brown|lazy/ig;

a.replace(パターン, 関数 replacer(match) {
  match.toUpperCase() を返します。
});
// 素早い茶色のキツネが怠惰な犬を飛び越えました。

「replace」メソッドの 2 番目のパラメータとしての置換関数は、複数のパラメータを受け入れることができます。このうち、最初のパラメータはキャプチャされたコンテンツ、2 番目のパラメータはキャプチャされたグループ マッチです (グループ マッチの数だけ対応するパラメータがあります)。さらに、最後に 2 つのパラメータを追加できます。最後から 2 番目のパラメータは、文字列全体におけるキャプチャされたコンテンツの位置 (たとえば、5 番目の位置から開始) であり、最後のパラメータは元の文字列です。以下は Web テンプレートの置き換えの例です。

変数価格 = {
  'p1': '$1.99',
  'p2': '$9.99',
  'p3': '$5.00'
};

var template = '<span id="p1"></span>'
  + '<span id="p2"></span>'
  + '<span id="p3"></span>';

テンプレート.replace(
  /(<span id=")(.*?)(">)(<\/span>)/g,
  function(match, $1, $2, $3, $4){
    $1 + $2 + $3 + 価格[$2] + $4 を返します。
  }
);
// "<span id="p1">$1.99</span><span id="p2">$9.99</span><span id="p3">$5.00</span>"

上記のコードのキャプチャ パターンには括弧が 4 つあるため、4 つのグループ一致が生成されます。これらは、マッチング関数の $1 から $4 で表されます。マッチング機能は、価格をテンプレートに挿入するために使用されます。

String.prototype.split()

文字列オブジェクトの split メソッドは、通常の規則に従って文字列を分割し、分割された部分からなる配列を返します。

str.split(区切り文字, [制限])

このメソッドは 2 つのパラメーターを受け入れます。最初のパラメーターは分離規則を示す正規表現で、2 番目のパラメーターは返される配列のメンバーの最大数です。

//不規則な分離
'a、b、c、d'.split(',')
// [ 'a', ' b', 'c', ' d' ]

//通常の区切り、余分なスペースを削除
'a、b、c、d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]

// 返された配列の最大のメンバーを指定します
'a、b、c、d'.split(/, */, 2)
[ 'a''b' ]

上記のコードは、正規表現を使用して部分文字列内のカンマの後のスペースを削除します。

//例1
'aaa*a*'.split(/a*/)
// [ '', '*', '*' ]

//例2
'aaa**a*'.split(/a*/)
// ["", "*", "*", "*"]

上記のコードの分割ルールは a 0 回以上です。正規表現のデフォルトは貪欲一致であるため、例 1 の最初の区切り文字は aaa、2 番目の区切り文字は a です。先頭の空の文字列を含む 3 つの部分に分割されます。例 2 の最初の区切り文字は aaa、2 番目の区切り文字は 0 a (つまり NULL 文字)、3 番目の区切り文字は a であるため、文字列は 4 つの部分に分割されます。

正規表現に括弧が含まれている場合は、括弧で囲まれた部分も配列メンバーとして返されます。

'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]

上記のコードの正規表現では括弧が使用されており、最初のグループの一致は「aaa」で、2 番目のグループの一致は「a」です。これらは両方とも配列メンバーとして返されます。

マッチングルール

正規表現のルールは非常に複雑なので、以下ではこれらのルールを 1 つずつ紹介します。

リテラル文字とメタキャラクター

正規表現のほとんどの文字は、「a」に一致する「/a/」や「b」に一致する「/b/」など、リテラルの意味を持ちます。正規表現内の文字がそのリテラルの意味のみを表す場合 (上記の「a」と「b」のように)、それらは「リテラル文字」と呼ばれます。

/dog/.test('老犬') // true

上記のコードの正規表現の「dog」はリテラル文字であるため、「/dog/」は「old Dog」に一致します。これは、「d」、「o」、「g」の 3 つの文字が結合されていることを意味するためです。 。

リテラル文字に加えて、一部の文字には特別な意味があり、リテラルの意味を表しません。これらは「メタキャラクター」と呼ばれるもので、主に以下のようなものがあります。

(1) ドット文字 (.)

ドット文字 (.) は、キャリッジ リターン (\r)、ライン フィード (\n)、行区切り文字 (\u2028)、および段落区切り文字 (\u2029) を除くすべての文字に一致します。コード ポイントが「0xFFFF」より大きい文字の場合、ドット文字は正しく一致せず、2 文字とみなされます。

/c.t/

上記のコードでは、c.t は、ct の間の任意の文字 (これら 3 つの文字が同じ行にある限り) (たとえば、catc2tc-t など) に一致しますが、 「オオバン」と一致しません。

(2)位置文字

位置文字は文字の位置を示すために使用され、主に 2 つの文字があります。

  • ^ は文字列の先頭を表します
  • $ は文字列の終了位置を表します
// テストは先頭になければなりません
/^test/.test('test123') // true

// テストは終了位置になければなりません
/test$/.test('新しいテスト') // true

// 開始位置から終了位置まではテストのみです
/^test$/.test('test') // true
/^test$/.test('テストテスト') // false

(3) セレクタ (|)

縦棒記号 (|) は正規表現の「または関係」(OR) を表します。つまり、cat|dogcat または dog と一致することを意味します。

/11|22/.test('911') // true

上記のコードでは、正規表現は「11」または「22」に一致する必要があることを指定しています。

複数のセレクターを組み合わせて使用​​できます。

// フレッド、バーニー、ベティのいずれかと一致します
/フレッド|バーニー|ベティ/

たとえば、セレクターには前後に複数の文字が含まれます。たとえば、/ab|cd/ は、b または c ではなく、ab または cd に一致することを意味します。この動作を変更したい場合は、括弧を使用できます。

/a( |\t)b/.test('a\tb') // true

上記のコードは、「a」と「b」の間にスペースまたはタブ文字があることを意味します。

他のメタキャラクタには、以下で説明する「\」、「*」、「+」、「?」、「()」、「[]」、「{}」などが含まれます。

エスケープ文字

正規表現で特別な意味を持つメタ文字と一致させるには、その前にバックスラッシュを付ける必要があります。たとえば、「+」に一致させるには、「+」と書きます。

/1+1/.test('1+1')
// 間違い

/1\+1/.test('1+1')
// 真実

上記のコードでは、プラス記号はメタキャラクターであり、それ自体を表していないため、最初の正規表現は一致しません。 2 番目の正規表現は、プラス記号をバックスラッシュでエスケープすることで正常に一致します。

正規表現では、バックスラッシュ エスケープが必要な文字が 12 文字あります: ^.[$()|*+ ?{、および \RegExp メソッドを使用して通常のオブジェクトを生成する場合、文字列は内部で 1 回エスケープされるため、エスケープに 2 つのスラッシュを使用する必要があることに注意することが重要です。

(新しい RegExp('1\+1')).test('1+1')
// 間違い

(新しい RegExp('1\\+1')).test('1+1')
// 真実

上記のコードでは、RegExp がコンストラクターとして使用されており、パラメーターは文字列です。ただし、文字列内ではバックスラッシュはエスケープ文字でもあるため、バックスラッシュで 1 回エスケープし、次に正規表現で 1 回エスケープするため、バックスラッシュを 2 回エスケープする必要があります。

特殊文字

正規表現は、印刷できない一部の特殊文字の表現方法を提供します。

  • \cXCtrl-[X] を意味します。ここで、X は制御文字と一致するために使用される A ~ Z の任意の英字です。
  • [\b] はバックスペース キー (U+0008) に一致します。\b と混同しないでください。
  • \n は改行キーと一致します。
  • \r はキャリッジ リターン キーに一致します。
  • \t はタブ文字 tab (U+0009) に一致します。
  • \v は垂直タブ文字 (U+000B) に一致します。
  • \f はフォーム フィード文字 (U+000C) に一致します。
  • \0null 文字 (U+0000) に一致します。
  • \xhh は、2 桁の 16 進数 (\x00-\xFF) で表される文字に一致します。
  • \uhhaha は、4 桁の 16 進数 (\u0000-\uFFFF) として表される Unicode 文字と一致します。

文字クラス

文字クラス (クラス) は、そのうちの 1 つが一致する限り、選択できる一連の文字があることを意味します。オプションの文字はすべて角かっこで囲みます。たとえば、[xyz] は、xyz のいずれかに一致することを意味します。

/[abc]/.test('hello world') // false
/[abc]/.test('apple') // true

上記のコードでは、文字列 hello world には 3 つの文字 abc が含まれていないため、文字列 apple には文字 a が含まれており、false が返されます。だから「true」を返します。

文字クラスには特別な意味を持つ 2 つの文字があります。

(1)キャレット(^)

角括弧内の最初の文字が [^] の場合、文字クラス内の文字に加えて、他の文字も一致できることを意味します。たとえば、[^xyz] は、xyz 以外のすべてが一致できることを意味します。

/[^abc]/.test('bbc ニュース') // true
/[^abc]/.test('bbc') // false

上記のコードでは、文字列「bbc news」には「a」、「b」、「c」以外の文字が含まれているため、「true」が返されます。文字列「bbc」には「a」、「b」は含まれません。 , c 以外の文字なので、false が返されます。

角括弧内に他の文字がない場合、つまり [^] のみがある場合は、改行を含むすべての文字と一致することを意味します。対照的に、メタ文字としてのドット (.) には改行が含まれません。

var s = 'はい、\n今日はよろしくお願いします!';

s.match(/y​​es.*day/) // null
s.match(/y​​es[^]*day/) // [ 'はい\n一日を楽しく']

上記のコードでは、文字列 s には改行文字が含まれており、ピリオドには改行文字が含まれていないため、最初の正規表現は一致しません。2 番目の正規表現 [^] にはすべての文字が含まれているため、一致します。成功する。

キャレットは文字クラスの最初の位置でのみ特別な意味を持ち、それ以外の場合は文字通りの意味を持つことに注意してください。

(2) ハイフン(-)

場合によっては、ハイフン (-) を使用して、連続する文字の範囲を示す、連続する文字シーケンスの省略表現が提供されます。たとえば、「[abc]」は「[a-c]」と書くことができ、「[0123456789]」は「[0-9]」と書くことができ、同様に「[A-Z]」は 26 個の大文字を表します。

/a-z/.test('b') // false
/[a-z]/.test('b') // true

上記のコードで、角括弧内にハイフン (ダッシュ) が含まれていない場合、これは省略の機能を持たず、文字通りの意味を表すだけであるため、文字 b は一致しません。ハイフンは、角括弧内で使用される場合にのみ、連続する文字のシーケンスを表します。

以下は、文字クラスの法的な略語です。

[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9-]
[1-31]

上記のコードの最後の文字クラス [1-31] は、1 から 31 までを表すのではなく、1 から 3 までを表すだけです。

ハイフンを使用して Unicode 文字の範囲を指定することもできます。

var str = "\u0130\u0131\u0132";
/[\u0128-\uFFFF]/.test(str)
// 真実

上記のコードでは、\u0128-\uFFFF は、コード ポイントが 0128 から FFFF までのすべての文字と一致することを意味します。

また、ハイフンを多用したり、範囲を広く設定したりしないでください。そうしないと、予期しない文字が選択される可能性があります。最も典型的な例は「[A-z]」です。表面的には、大文字の「A」から小文字の「z」までの 52 文字が選択されます。ただし、ASCII エンコードのため、大文字と小文字の間にはまだ隙間があります。他の文字を使用すると、予期しない結果が発生する可能性があります。

/[A-z]/.test('\\') // true

上記コードでは、バックスラッシュ('\')のASCIIコードが大文字と小文字の間にあるため、結果が選択されます。

事前定義されたパターン

事前定義されたパターンは、いくつかの一般的なパターンの短縮形です。

  • \d は 0 ~ 9 の任意の数値に一致し、[0-9] と同等です。
  • \D は、0 ~ 9 を除くすべての文字に一致します。これは、[^0-9] と同等です。
  • \w は、任意の文字、数字、アンダースコアに一致します。これは、[A-Za-z0-9_] と同等です。
  • \W (すべての文字、数字、アンダースコアを除く)。[^A-Za-z0-9_] と同等。
  • \s はスペース (改行、タブ、スペースなどを含む) に一致します。これは [ \t\r\n\v\f] と同等です。
  • \S はスペース以外の文字に一致し、[^ \t\r\n\v\f] と同等です。
  • \b は単語の境界に一致します。
  • \B は単語以外の境界、つまり単語の内部に一致します。

以下にいくつかの例を示します。

// \s の例
/\s\w*/.exec('hello world') // [" ワールド"]

// \b の例
/\bworld/.test('hello world') // true
/\bworld/.test('hello-world') // true
/\bworld/.test('helloworld') // false

// \B の例
/\Bworld/.test('hello-world') // false
/\Bworld/.test('helloworld') // true

上記のコードでは、「\s」はスペースを表すため、一致結果にはスペースが含まれます。 \b は単語の境界を表すため、一致する前に単語 world の先頭が独立している必要があります (単語の終わりが独立しているかどうかは指定されていません)。同様に、\B は非単語の境界を表し、単語 world の先頭が独立していない場合にのみ一致します。

通常、正規表現は改行文字 (\n) に遭遇すると照合を停止します。

var html = "<b>こんにちは</b>\n<i>世界!</i>";

/.*/.exec(html)[0]
// "<b>こんにちは</b>"

上記のコードでは、文字列 html に改行文字が含まれており、結果のドット文字 (.) が改行文字と一致しないため、一致結果が本来の意図と一致しない可能性があります。このとき、\s 文字クラスを使用すると、改行を含めることができます。

var html = "<b>こんにちは</b>\n<i>世界!</i>";

/[\S\s]*/.exec(html)[0]
// "<b>こんにちは</b>\n<i>世界!</i>"

上記のコードでは、[\S\s] はすべての文字を指します。

繰り返し授業

パターンの一致の正確な数。中括弧 ({}) を使用して表現されます。 「{n}」は正確に「n」回繰り返すことを意味し、「{n,}」は少なくとも「n」回繰り返すことを意味し、「{n,m}」は「n」回以上「m」回以下繰り返すことを意味します` 二流。

/lo{2}k/.test('look') // true
/lo{2,5}k/.test('looook') // true

上記のコードでは、最初のパターンは「o」が連続して 2 回出現することを指定し、2 番目のパターンは「o」が連続して 2 ~ 5 回出現することを指定します。

量指定子

数量子は、特定のパターンの出現数を設定するために使用されます。

  • 疑問符「?」は、パターンが 0 回または 1 回出現することを示し、これは「{0, 1}」と同等です。
  • * アスタリスクは、パターンが 0 回以上出現することを示し、{0,} と同等です。
  • + プラス記号は、パターンが 1 回以上出現することを示します。これは、{1,} と同等です。
// t は 0 回または 1 回出現します
/t?est/.test('test') // true
/t?est/.test('est') // true

// t が 1 回以上出現する
/t+est/.test('test') // true
/t+est/.test('ttest') // true
/t+est/.test('est') // false

// t が 0 回以上出現する
/t*est/.test('test') // true
/t*est/.test('ttest') // true
/t*est/.test('tttest') // true
/t*est/.test('est') // true

貪欲モード

前のセクションの 3 つの量指定子文字はすべて、デフォルトで可能な最大範囲まで一致します。つまり、次の文字が一致ルールを満たさなくなるまで一致します。これは貪欲モードと呼ばれます。

vars = 'aaa';
s.match(/a+/) // ["aaa"]

上記のコードでは、パターンは /a+/ です。これは、1 つまたは複数の a と一致することを意味します。では、いくつの a が一致するでしょうか。デフォルトは貪欲モードなので、文字「a」が出現しなくなるまで一致するため、一致結果は 3「a」になります。

貪欲モードに加えて、可能な限り最小の一致である非貪欲モードもあります。一致が見つかるとすぐに、それ以上のチェックは行わずに結果が返されます。貪欲モードを非貪欲モードに変更する場合は、量指定子の後に疑問符を追加できます。

vars = 'aaa';
s.match(/a+?/) // ["a"]

上記の例では、パターンの最後に疑問符 /a+?/ が追加されます。このとき、条件が満たされると、+ は一致しなくなります。 ? は、「a」が見つかる限り、それ以上のマッチングは行われないことを意味します。

非貪欲モードのプラス記号 (+?) に加えて、非貪欲モードのアスタリスク (*?) および非貪欲モードの疑問符 (??) もあります。

  • +?: 特定のパターンが 1 回以上出現し、マッチング時に非貪欲モードが使用されることを示します。
  • *?: パターンが 0 回以上出現し、マッチング時に非貪欲モードが使用されることを示します。
  • ??: テーブル内の特定のパターンが 0 回または 1 回出現し、マッチング時に非貪欲モードが使用されます。
'abb'.match(/ab*/) // ["abb"]
'abb'.match(/ab*?/) // ["a"]

'abb'.match(/ab?/) // ["ab"]
'abb'.match(/ab??/) // ["a"]

上記の例では、「/ab*/」は、「a」の後に複数の「b」がある場合、できるだけ多くの「b」に一致することを意味し、「/ab*?/」は、より少ない数の「b」に一致することを意味します。可能な限り、それは 0 b です。

修飾子

修飾子はパターンの追加ルールを表し、通常のパターンの最後に配置されます。

修飾子は個別に使用することも、組み合わせて使用​​することもできます。

// 単一の修飾子
var regex = /test/i;

//複数の修飾子
var regex = /test/ig;

(1)g 修飾子

デフォルトでは、最初に一致が成功すると、通常のオブジェクトは下位一致を停止します。 「g」修飾子はグローバル一致を表し、これを追加すると、通常のオブジェクトはすべての修飾された結果と一致し、主に検索と置換に使用されます。

var 正規表現 = /b/;
var str = 'アバ';

regex.test(str); // true
regex.test(str); // true
regex.test(str); // true

上記のコードでは、通常のパターンに「g」修飾子が含まれておらず、毎回文字列の先頭からマッチングが開始されます。したがって、3 回連続して一致した後、「true」が返されます。

var regex = /b/g;
var str = 'アバ';

regex.test(str); // true
regex.test(str); // true
regex.test(str); // false

上記のコードでは、通常のパターンに「g」修飾子が含まれており、毎回、最後に成功した一致から逆方向に一致します。文字列「abba」には「b」が 2 つしかないため、最初の 2 つの一致結果は「true」、3 番目の一致結果は「false」になります。

(2)i 修飾子

デフォルトでは、通常のオブジェクトは大文字と小文字を区別します。「i」修飾子を追加すると、大文字と小文字が区別されます (ignoreCase)。

/abc/.test('ABC') // false
/abc/i.test('ABC') // true

上記のコードは、「i」修飾子を追加した後は大文字と小文字が考慮されないため、パターン「abc」が文字列「ABC」と一致することを示しています。

(3)m 修飾子

m 修飾子は複数行モード (複数行) を示し、^$ の動作を変更します。デフォルトでは (つまり、「m」修飾子が追加されていない場合)、「^」と「$」は文字列の先頭と末尾に一致します。「m」修飾子を追加すると、「^」と「$」も一致します。 match 行の先頭と末尾を一致させます。つまり、^$ は改行 (\n) を認識します。

/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true

上記のコードでは、文字列の最後に改行文字があります。 m 修飾子が追加されていない場合、文字列の末尾が world ではないため、一致は失敗します。修飾子を追加すると、$ が行の末尾と一致するようになります。

/^b/m.test('a\nb') // true

上記のコードでは、行の先頭にある 'b' と一致する必要があります。 'm' 修飾子が追加されていない場合、'b' は文字列の先頭にのみ存在できることを意味します。 m 修飾子を追加すると、改行文字 \n も行の先頭とみなされます。

グループマッチング

(1) 概要

正規表現内の括弧はグループの一致を表し、括弧内のパターンを使用してグループの内容を一致させることができます。

/fred+/.test('fredd') // true
/(fred)+/.test('fredfred') // true

上記のコードでは、最初のパターンには括弧がありません。結果の + は文字 d の繰り返しを意味するだけです。2 番目のパターンには括弧があり、結果の + は単語 fred との一致を意味します。

これはグループキャプチャの別の例です。

var m = 'abcabc'.match(/(.)b(.)/);
メートル
// ['abc', 'a', 'c']

上記のコードでは、正規表現 /(.)b(.)/ は合計 2 つの括弧を使用しており、最初の括弧は a をキャプチャし、2 番目の括弧は c をキャプチャします。

グループ マッチングを使用する場合、g 修飾子を同時に使用することはお勧めできません。そうしないと、match メソッドがグループの内容を取得できなくなります。

var m = 'abcabc'.match(/(.)b(.)/g);
m // ['abc', 'abc']

上記のコードでは、「g」修飾子を含む正規表現が使用されているため、「match」メソッドは式全体に一致する部分のみをキャプチャします。このとき、正規表現の「exec」メソッドを使用し、ループと連携して各ラウンドの一致するグループのキャプチャを読み取る必要があります。

var str = 'abcabc';
var reg = /(.)b(.)/g;
while (true) {
  var result = reg.exec(str);
  if (!result) ブレーク;
  console.log(結果);
}
// ["abc", "a", "c"]
// ["abc", "a", "c"]

正規表現内で、「\n」を使用して、括弧で一致するコンテンツを参照することもできます。「n」は、対応する括弧の順序を示す 1 から始まる自然数です。

/(.)b(.)\1b\2/.test("abcabc")
// 真実

上記のコードでは、「\1」は最初の括弧 (つまり「a」) に一致するコンテンツを表し、「\2」は 2 番目の括弧 (つまり「c」) に一致するコンテンツを表します。

別の例を示します。

/y(..)(.)\2\1/.test('yabccab') // true

括弧は入れ子にすることもできます。

/y((..)\2)\1/.test('yabababab') // true

上記のコードでは、「\1」は外側の括弧を指し、「\2」は内側の括弧を指します。

グループ マッチングは非常に便利です。Web ページ タグのマッチングの例を次に示します。

var tagName = /<([^>]+)>[^<]*<\/\1>/;

tagName.exec("<b>太字</b>")[1]
// 'b'

上記のコードでは、括弧は山括弧内のタグと一致し、「\1」は対応する終了タグを表します。

上記のコードを少し変更すると、属性を持つタグをキャプチャできます。

var html = '<b class="hello">こんにちは</b><i>世界</i>';
var タグ = /<(\w+)([^>]*)>(.*?)<\/\1>/g;

var match = tag.exec(html);

match[1] // "b"
match[2] // " class="hello""
match[3] // 「こんにちは」

一致 = tag.exec(html);

match[1] // "i"
match[2] // ""
match[3] // 「ワールド」

(2)非捕獲グループ

(?:x) は非キャプチャ グループと呼ばれます。これは、グループの一致する内容が返されない、つまり括弧が一致結果に含まれないことを意味します。

非キャプチャ グループの役割 このシナリオを考慮してください。foo または foofoo に一致する必要があると仮定して、正規表現は /(foo){1, 2}/ として記述する必要がありますが、これが占有します。グループマッチング。このとき、非キャプチャ グループを使用して正規表現を /(?:foo){1, 2}/ に変更できます。その機能は前の正規表現と同じですが、出力されません。括弧内の内容は個別に記述します。

以下の例を参照してください。

var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"]

上記のコードのパターンでは、合計 2 つの括弧が使用されています。最初の括弧は非キャプチャ グループであるため、最終的に返される結果には最初の括弧はなく、2 番目の括弧の一致する内容のみが含まれます。

以下は、URL を分解するために使用される正規表現です。

// 通常の一致
var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;

url.exec('http://google.com/');
// ["http://google.com/", "http", "google.com", "/"]

// 非キャプチャグループマッチング
var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;

url.exec('http://google.com/');
// ["http://google.com/", "google.com", "/"]

上記のコードでは、前者の正規表現は通常の一致であり、最初の括弧はネットワーク プロトコルを返します。後者の正規表現は非キャプチャ一致であり、ネットワーク プロトコルは返される結果に含まれません。

(3) 先行主張

x(?=y) は肯定先読みと呼ばれ、xy の前にのみ一致し、y は返される結果には含まれません。たとえば、パーセント記号が後に続く数値と一致させるには、「/\d+(?=%)/」と書くことができます。

「先読みアサーション」では括弧内の部分は返されません。

var m = 'abc'.match(/b(?=c)/);
m // ["b"]

上記のコードは先読みアサーションを使用しています。bc の前に一致しますが、括弧に対応する c は返されません。

(4) 先行件否定主張

x(?!y) は負の先読みと呼ばれ、xy より前にない場合にのみ一致し、y は返される結果に含まれません。たとえば、パーセント記号が続かない数値と一致するには、「/\d+(?!%)/」と書きます。

/\d+(?!\.)/.exec('3.14')
// ["14"]

上記のコードでは、正規表現は小数点より前にない数値のみが一致することを指定しているため、返される結果は「14」になります。

「プリエンプティブ否定アサーション」の場合、括弧内の部分は返されません。

var m = 'abd'.match(/b(?!c)/);
m // ['b']

上記のコードでは、先読み否定アサーションを使用しています。「b」は「c」の前に一致しないため、括弧に対応する「d」は返されません。

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0