Как захватить произвольное количество групп в JavaScript Regexp? - PullRequest
74 голосов
/ 21 августа 2010

Я ожидал бы, что эта строка JavaScript:

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

вернет что-то вроде:

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

, но вместо этого он возвращает только последнее захваченное совпадение:

["foo bar baz", " baz"]

Есть ли способ получить все захваченные спички?

Ответы [ 4 ]

80 голосов
/ 21 августа 2010

Когда вы повторяете группу захвата, в большинстве ароматов сохраняется только последний захват; любой предыдущий захват перезаписывается. В некотором аромате, например .NET, вы можете получить все промежуточные записи, но это не так с Javascript.

То есть в Javascript, если у вас есть шаблон с N группами захвата, вы можете захватывать только ровно N строк за матч, даже если некоторые из этих групп были повторены.

В общем, в зависимости от того, что вам нужно сделать:

  • Если это вариант, вместо этого разделить на разделители
  • Вместо сопоставления /(pattern)+/, возможно, совпадение /pattern/g, возможно, в цикле exec
    • Обратите внимание, что эти два не совсем эквивалентны, но это может быть вариант
  • Выполнить многоуровневое сопоставление:
    • Захват повторяемой группы в одном матче
    • Затем запустите другое регулярное выражение, чтобы разбить это соответствие на части

Ссылки


Пример

Вот пример соответствия <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 голосов
/ 21 августа 2010

Как насчет этого?"foo bar baz".match(/(\w+)+/g)

5 голосов
/ 21 августа 2010

Если у вас нет более сложных требований к разделению строк, вы можете разделить их, а затем вернуть исходную строку с ними:

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);
4 голосов
/ 21 августа 2010

попробуйте использовать 'g':

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