Итератор регулярного выражения JavaScript для извлечения групп
скажем, мы имеем следующий текст: "1 a, 2 b, 3 c, 4 d" и следующее выражение:/\ d (\ w)/g
то, что мы хотим сделать, - извлечь a, b, c, d, как это обозначено регулярным выражением.
К сожалению, "1 a, 2 b, 3 c, 4 d".match(/\ d (\ w)/g) создаст массив: 1 a, 2 b, 3 c, 4 d и RegExp. будет содержать только группы из последнего совпадения, то есть RegExp. $1 == 'd'.
как я могу перебирать это регулярное выражение, чтобы я мог также извлекать группы... Я ищу решение, которое также эффективно с точки зрения памяти, т.е. какой-то объект итератора
EDIT:
Он должен быть общим. Я просто представляю простой пример. Одним из решений является цикл над массивом и повторное применение регулярного выражения для каждого элемента без глобального флага, но я считаю это решение немного глупым, хотя кажется, что это единственный способ сделать это.
Ответы
Ответ 1
var myregexp = /\d (\w)/g;
var match = myregexp.exec(subject);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
match = myregexp.exec(subject);
}
(бесстыдно взято из RegexBuddy)
Ответ 2
Более короткое, более простое (хотя и менее эффективное) решение заключается в использовании String.prototype.replace. replace уникальна тем, что она неявно выполняет итерацию по всем совпадениям и выполняет функцию для каждого совпадения. Конечно, вы можете использовать эту функцию для фактической замены текста, но, несмотря на то, что имя функции действительно не требуется:
"1 a,2 b,3 c,4 d".replace(/\d (\w)/g, function(complete_match, matched_letter) {
console.log(matched_letter);
});
Это будет вести журнал a
, b
, c
, затем d
на консоли. (Также будет возвращено "undefined,undefined,undefined,undefined"
, но здесь нас это не волнует.)
В общем случае аргумент функции для замены вызывается со следующими параметрами:
function(match, p1, p2, [...], offset, string)
-
match
- соответствующая подстрока.
-
p1
и т.д. - это совпадающие захваченные группы, если они есть. Группы находятся в порядке открывающей скобки, которой они соответствуют (то есть левый первый, первый внешний). Если группа соответствует нескольким подстрокам (т.е. В сценарии (.)+
), захватывается только последняя (самая правая) подстрока.
-
offset
- это индекс в исходной строке этого совпадения
-
string
- это строка, на которой был вызван replace
.
Ручная итерация, скорее всего, более эффективна, но этот метод не медленный, и он короче и (IMHO) легче читать; Я склонен использовать этот шаблон в ручном цикле.
Ответ 3
Это будет работать:
"1 a,2 b,3 c,4 d".match(/\w(?:,|$)/g).join(' '); // => "a, b, c, d"
Если вам нужна итерация:
var r = /\d (\w)/g,
s = "1 a,2 b,3 c,4 d",
m;
while ( m = r.exec(s) ) {
// `m` is your match, `m[1]` is the letter
}