web-dev-qa-db-ja.com

JavaScript Regexpで任意の数のグループをキャプチャする方法は?

私はこのJavaScript行を期待しています:

"foo bar baz".match(/^(\s*\w+)+$/)

次のようなものを返すには:

["foo bar baz", "foo", " bar", " baz"]

代わりに、最後にキャプチャされた一致のみを返します。

["foo bar baz", " baz"]

キャプチャされたすべての一致を取得する方法はありますか?

75
disc0dancer

キャプチャグループを繰り返すと、ほとんどのフレーバーで、最後のキャプチャのみが保持されます。以前のキャプチャはすべて上書きされます。いくつかのフレーバー、例えば.NETでは、すべての中間キャプチャを取得できますが、Javascriptの場合はそうではありません。

つまり、Javascriptで、[〜#〜] n [〜#〜]キャプチャグループを持つパターンがある場合、正確にキャプチャすることしかできません[〜#〜] n [〜#〜]これらのグループの一部が繰り返された場合でも、一致ごとの文字列。

したがって、一般的に言えば、何をする必要があるかに応じて:

  • オプションの場合は、代わりに区切り文字で分割します
  • /(pattern)+/に一致する代わりに、おそらく/pattern/gに一致し、おそらくexecループに一致します
    • これら2つは完全に同等ではないことに注意してくださいが、オプションである可能性があります
  • マルチレベルマッチングを実行します。
    • 繰り返されるグループを1回のマッチでキャプチャする
    • 次に、別の正規表現を実行して、その一致をバラバラにします

参照資料


以下は、execループを使用して、テキスト内の<some;words;here>を照合し、;で分割して個々の単語を取得する例です( ideone.comも参照 =):

var text = "a;b;<c;d;e;f>;g;h;i;<no no no>;j;k;<xx;yy;zz>";

var r = /<(\w+(;\w+)*)>/g;

var match;
while ((match = r.exec(text)) != null) {
  print(match[1].split(";"));
}
// c,d,e,f
// xx,yy,zz

使用されるパターンは次のとおりです。

      _2__
     /    \
<(\w+(;\w+)*)>
 \__________/
      1

これは、<Word><Word;another><Word;another;please>などに一致します。グループ2は、任意の数の単語をキャプチャするために繰り返されますが、最後のキャプチャのみを保持できます。単語のリスト全体がグループ1によってキャプチャされます。この文字列は、セミコロン区切り記号のsplitです。

関連する質問

83

これはどうですか? "foo bar baz".match(/(\w+)+/g)

7
meder omuraliev

文字列をどのように分割するかについてより複雑な要件がない限り、それらを分割し、初期文字列を返すことができます。

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);
5
g.d.d.c

「g」を使用してみてください。

"foo bar baz".match(/\w+/g)
4
Jet