Лучший способ хранения групп захвата JS Regex в массиве?
Именно то, что спрашивает название. Я приведу несколько примеров, объясняя свой вопрос.
Тестовая строка:
var test = "#foo# #foo# bar #foo#";
Скажем, я хочу извлечь весь текст между #
(все foo
, но не bar
).
var matches = test.match(/#(.*?)#/g);
Используя .match
, как указано выше, он сохранит все совпадения, но он просто выбросит группы захвата, которые, как кажется.
var matches2 = /#(.*?)#/g.exec(test);
Метод .exec
, по-видимому, возвращает только строку с результатом первого результата в позиции 0
массива и мою единственную группу захвата этого совпадения в позиции 1
.
Я исчерпал SO, Google и MDN, ища ответ безрезультатно.
Итак, мой вопрос заключается в том, есть ли лучший способ сохранить только согласованные группы захвата, чем прокручивать его с помощью .exec
и вызывать array.push
для хранения захваченных групп?
Мой ожидаемый массив для теста выше должен быть:
[0] => (string) foo
[1] => (string) foo
[2] => (string) foo
Pure JS и ответы jQuery принимаются, дополнительные файлы cookie, если вы отправляете JSFiddle с помощью console.log
. =]
Ответы
Ответ 1
Вы можете использовать .exec
тоже, как показано ниже, для построения массива
var arr = [],
s = "#foo# #bar# #test#",
re = /#(.*?)#/g,
item;
while (item = re.exec(s))
arr.push(item[1]);
alert(arr.join(' '));
Рабочая скрипта
Найдено здесь
Ну, у него все еще есть цикл, если вам не нужен цикл, я думаю, вам нужно пойти с .replace()
. В этом случае код будет выглядеть как
var arr = [];
var str = "#foo# #bar# #test#"
str.replace(/#(.*?)#/g, function(s, match) {
arr.push(match);
});
Проверьте эти строки из MDN DOC, в котором объясняется ваш запрос о том, как exec
обновляет свойство lastIndex
, я думаю,
Если ваше регулярное выражение использует флаг "g", вы можете использовать exec метод несколько раз, чтобы найти последовательные совпадения в одной строке.
Когда вы это сделаете, поиск начинается с подстроки str, указанной в свойство lastIndex регулярного выражения (тест также будет продвигаться вперед свойство lastIndex).
Ответ 2
Я не уверен, что это ответ, который вы ищете, но вы можете попробовать следующий код:
var matches = [];
var test = "#foo# #foo# bar #foo#";
test.replace(/#(.*?)#/g, function (string, match) {
matches.push(match);
});
alert(JSON.stringify(matches));
Ответ 3
data.replace(/.*?#(.*?#)/g, '$1').split(/#/)
Нет циклов, нет функций.
Ответ 4
Другая мысль, хотя exec эффективна.
var s= "#foo# #foo# bar #foo#";
s= s.match(/#([^#])*#/g).join('#').replace(/^#+|#+$/g, '').split(/#+/);
Ответ 5
Если кто-то приходит с аналогичной потребностью в моей работе, мне нужна соответствующая функция для обработчика конфигурации URL-адреса Django, который может передавать "аргументы" пути к контроллеру. Я придумал это. Естественно, это не сработает, если совпадение "$", но оно не сломается "на $1.00". Это немного более явным, чем необходимо. Вы могли бы просто вернуть matchedGroups из инструкции else и не беспокоиться о тесте for loop, но;; в середине объявления цикла часто уродуют людей.
var url = 'http://www.somesite.com/calendar/2014/june/6/';
var calendarMatch = /^http\:\/\/[^\/]*\/calendar\/(\d*)\/(\w*)\/(\d{1,2})\/$/;
function getMatches(str, matcher){
var matchedGroups = [];
for(var i=1,groupFail=false;groupFail===false;i++){
var group = str.replace(matcher,'$'+i);
groupFailTester = new RegExp('^\\$'+i+'$');
if(!groupFailTester.test(group) ){
matchedGroups.push(group);
}
else {
groupFail = true;
}
}
return matchedGroups;
}
console.log( getMatches(url, calendarMatch) );