Як захопити довільну кількість груп у 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.