Проблема в том, что регулярное выражение сохраняет свойство lastIndex
, которое отслеживает конечный индекс последнего совпадения.В
foo {{partialCount}} of {{count}} bars
сопоставление
{{partialCount}}
приводит к тому, что свойство lastIndex
впоследствии устанавливается на 20
- местоположение после второго }
.
Затем, когда вы переназначите строку на
foo 3 of {{count}} bars
, используя то же регулярное выражение, чтобы попытаться найти соответствие, начнется с индекса 20 этой строки, которая равна мимо часть {{count}}
, поэтому совпадение не удается.
Один из вариантов - вручную сбросить lastIndex
на 0 каждый раз:
const getInjectedPhrase = (phrase, injections, doubleCheck) => {
let value = phrase;
// only need to attempt to replace the injectables in the phrase is we've been passed injections
if (injections && phrase.length > 1) {
const injectableRegex = /{{\s?([\w-]+)\s?}}/g; // find any matching injectable, and extract its key
let match;
window.console.log('initial phrase:', phrase);
// check if dictionary value contains injectable sections ie. sections surrounded by {{ }}
do {
injectableRegex.lastIndex = 0;
match = injectableRegex.exec(value);
if (match) {
/*
match[0] -> {{ x }}
match[1] -> x
*/
const injectionValue = injections[match[1]];
const injectionValueType = typeof injectionValue;
if (
injectionValueType === "string" ||
injectionValueType === "number"
) {
// globally replace the value with the injection's value
value = value.replace(new RegExp(match[0], "g"), `${injectionValue}`);
window.console.log('partial replace phrase:', value);
}
}
} while (match !== null);
}
window.console.log('returned phrase:', value);
return value;
};
window.console.log('WITHOUT DOUBLE CHECKING');
getInjectedPhrase(
"foo {{partialCount}} of {{count}} bars", {
partialCount: 3,
count: 4
},
false
);
Лучшим вариантом будет replace
все сразу , с функцией обратного вызова, нет необходимости вручную повторять, заменять и сбрасыватьобъект регулярного выражения:
const getInjectedPhrase = (str, obj) => str.replace(
/{{\s?([\w-]+)\s?}}/g,
(_, key) => obj[key]
);
console.log(
getInjectedPhrase(
"foo {{partialCount}} of {{count}} bars", {
partialCount: 3,
count: 4
},
)
);