Як захопити довільну кількість груп у JavaScript Regexp?


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циклі
    • Зверніть увагу, що ці два не зовсім рівнозначні, але це може бути варіант
  • Виконайте багаторівневу відповідність:
    • Захоплення повторної групи за один матч
    • Потім запустіть ще один регулярний вираз, щоб розірвати цей збіг

Список літератури


Приклад

Ось приклад відповідності <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 bar baz "]
disc0dancer

це спрацює, якщо ви зміните його на регулярний вираз @ Jet нижче. "foo bar baz".match(/\w+/g) //=> ["foo", "bar", "baz"]. він ігнорує відповідну рядок спереду, але все ще є розумною альтернативою.
Джед Шнайдер,

6

Якщо у вас немає більш складної вимоги щодо того, як ви розділяєте свої рядки, ви можете розділити їх, а потім повернути з ними початковий рядок:

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

1
Це врешті-решт стало просто тією порадою, яка мені потрібна, щоб розбудити мене від того, що, принаймні для моєї поточної програми, мені не потрібно нічого більш складного, ніж split ().
Гефест

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.