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


84

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

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

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

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

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

["foo bar baz", " baz"]

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

回答:


93

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

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

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

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

参考文献


これ<some;words;here>は、テキスト内で一致し、execループを使用し、次に分割し;て個々の単語を取得する例です(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セミコロン区切り文字になります。

関連する質問


7

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


コードは機能しますが、私の例にグローバルフラグを追加しても、問題は解決しません。 "foo bar baz" .match(/ ^(\ s * \ w +)+ $ / g)は["foo barbaz"]を返します
disc0dancer 2010

以下の@Jetの正規表現に変更すると機能します。"foo bar baz".match(/\w+/g) //=> ["foo", "bar", "baz"]。前面の一致した文字列を無視しますが、それでも妥当な代替手段です。
Jed Schneider

6

文字列を分割する方法についてより複雑な要件がない限り、文字列を分割してから、最初の文字列を一緒に返すことができます。

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);

1
これは、少なくとも現在のアプリケーションでは、split()よりも高度なものは必要ないという事実に目覚めるために必要なアドバイスの一部にすぎませんでした。
ヘファイストス2014年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.