Reputation: 4351
Can anyone see why the following code does not perform the regex operations on all the {{ ... }} placeholders? The input string below is just a stripped down version of the original.
https://jsfiddle.net/2L12jr3u/2/
var input = "{{ %1$@ }} / {{ %1$@ }} ({{ %2$@ }}) {{ %1$@ }} {{ %1$@ }} {{ %1$d }} {{ %1$@ }} of {{ %2$d }} of {{ %3$d }}";
var regex = /(\{\{ \%(\d)\$(.) \}\})/g;
var match;
while (match = regex.exec(input)) {
console.log(match);
input = input.replace(match[0], '%@' + match[2]);
}
console.log(input);
Upvotes: 2
Views: 50
Reputation: 533
First I suggest to remove unnecessary groups in the regular expression,
/\{\{ %(\d)\$. \}\}/g
instead of /(\{\{ %(\d)\$(.) \}\})/g
.
Then, to replace you can use a much shorter approach (and also more clear in my oppinion):
var input = "{{ %1$@ }} / {{ %1$@ }} ({{ %2$@ }}) {{ %1$@ }} {{ %1$@ }} {{ %1$d }} {{ %1$@ }} of {{ %2$d }} of {{ %3$d }}";
var output = input.replace(/\{\{ %(\d)\$. \}\}/g, "%@$1");
The final value of output is %@1 / %@1 (%@2) %@1 %@1 %@1 %@1 of %@2 of %@3
Upvotes: 0
Reputation: 193301
Since you are using exec
to match multiple occurrences, in each iteration it starts searching from the last matched index:
If your regular expression uses the "g" flag, you can use the exec() method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property (test() will also advance the lastIndex property).
In your case it's much simpler and cleaner to use String.prototype.replace
method:
var input = "{{ %1$@ }} / {{ %1$@ }} ({{ %2$@ }}) {{ %1$@ }} {{ %1$@ }} {{ %1$d }} {{ %1$@ }} of {{ %2$d }} of {{ %3$d }}";
var regex = /(\{\{ %(\d)\$(.) \}\})/g;
input = input.replace(regex, '%@$2');
alert(input);
Upvotes: 2
Reputation: 627607
It is because you change the input
variable while exec
has not finished.
The index is moving forward, but the string gets shorter.
Add another variable, or wrap in a separate function, or use replace
as suggested by @dfsq:
var input = "{{ %1$@ }} / {{ %1$@ }} ({{ %2$@ }}) {{ %1$@ }} {{ %1$@ }} {{ %1$d }} {{ %1$@ }} of {{ %2$d }} of {{ %3$d }}";
var regex = /(\{\{ \%(\d)\$(.) \}\})/g;
var output = input;
var match;
while (match = regex.exec(input)) {
console.log(match);
output = output.replace(match[1], '%@' + match[2]);
}
alert(output);
Upvotes: 3