У меня есть такая строка: "hello %{name} good %{middle} bye"
.
Я пытаюсь найти эффективный способ извлечь значения между фигурными скобками, поэтому в идеале у меня должен получиться массив ["name", "middle"]
.
Используя match
, я почти могу туда добраться. Следующие результаты возвращают: ['%{name}', '%{middle}']
:
"hello %{name} good %{middle} bye".match(/%{([\w]+)}/g)
Я не уверен, почему в возврат включены символы %
, {
и }
.
Как мне настроить регулярное выражение так, чтобы оно соответствовало только name
и middle
?
@anubhava, который возвращает массив массивов
Почему? См. MDN. Если используется флаг g
, будут возвращены все результаты, соответствующие полному регулярному выражению, но группы захвата не включаются.
@AndrewParks: Да, я знаю. Группы захвата начинаются с позиции 1 в каждом элементе.
Вы можете использовать именованную группу захвата. В приведенном ниже примере мы назовем его value
, а затем извлекем эти значения во время итерации совпадений с регулярным выражением:
let s = "hello %{name} good %{middle} bye"
let r = [...s.matchAll(/%{(?<value>[\w]+)}/g)].map(i => i.groups.value)
console.info(r)
Пытаться
const str = "hello %{name} good %{middle} bye";
const regex = /%\{([\w]+)\}/g;
let matches;
const result = [];
while ((matches = regex.exec(str)) !== null) {
result.push(matches[1]);
}
console.info(result) // [ 'name', 'middle', 'another', 'example' ]
Что касается вашего вопроса, почему в возврат включены символы %, { и }?
потому что функция match() в JavaScript возвращает всю совпавшую подстроку, включая %{ и }.
Решением этой проблемы было бы использование match[1] (или эквивалента в цикле с exec()), позволяющего получить доступ только к содержимому, заключенному в круглые скобки ( ) в вашем шаблоне регулярного выражения.
Вам нужно изменить выражение регулярного выражения, чтобы оно фиксировало значения внутри фигурных скобок без символов %, { и }, вы можете немного изменить его.
Существующие: /%{([\w]+)}/g
=> /%\{(\w+)\}/g
См. приведенные ниже примеры:
const str = "hello %{name} good %{middle} bye";
const str1 = "hello %{aaa} good %{bbbb} bye";
const str2 = "hello %{xyz} %{gtr} %{pqr} bye";
const matches = str.match(/%\{(\w+)\}/g);
const matches1 = str1.match(/%\{(\w+)\}/g);
const matches2 = str2.match(/%\{(\w+)\}/g);
const values = matches.map(match => match.slice(2, -1));
const values1 = matches1.map(match => match.slice(2, -1));
const values2 = matches2.map(match => match.slice(2, -1));
console.info(JSON.stringify(values));
console.info(JSON.stringify(values1));
console.info(JSON.stringify(values2));
Кроме того, этого можно достичь и с помощью подхода, не основанного на регулярных выражениях:
const str = "hello %{name} %{world} %{middle} bye";
const str1 = "hello %{aaa} %{bye} %{bbbb} bye";
const str2 = "hello %{xyz} %{gtr} %{pqr} bye";
const startDelimiter = "%{";
const endDelimiter = "}";
function extractValues(input, startDelimiter, endDelimiter) {
const values = [];
let startIndex = 0;
while ((startIndex = input.indexOf(startDelimiter, startIndex)) !== -1) {
startIndex += startDelimiter.length;
const endIndex = input.indexOf(endDelimiter, startIndex);
if (endIndex === -1) {
break;
}
const value = input.substring(startIndex, endIndex);
values.push(value);
startIndex = endIndex + endDelimiter.length;
}
return values;
}
const result = extractValues(str, startDelimiter, endDelimiter);
const result1 = extractValues(str1, startDelimiter, endDelimiter);
const result2 = extractValues(str2, startDelimiter, endDelimiter);
console.info(JSON.stringify(result));
console.info(JSON.stringify(result1));
console.info(JSON.stringify(result2));
Попробуйте:
[..."hello %{name} good %{middle} bye".matchAll(/%{([\w]+)}/g)]