2015-04-23 2 views
2

Может ли кто-нибудь понять, почему следующий код не выполняет операции регулярного выражения на всех {{...}} местах-заполнителях? Строка ввода ниже - это просто урезанная версия оригинала.Замена Regex не выполняется во всех совпадениях

https://jsfiddle.net/2L12jr3u/2/

var input = "{{ %[email protected] }}/{{ %[email protected] }} ({{ %[email protected] }}) {{ %[email protected] }} {{ %[email protected] }} {{ %1$d }} {{ %[email protected] }} 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); 
+0

Что должен выглядеть результат? – garryp

ответ

2

Поскольку вы используете exec, чтобы соответствовать несколько экземпляров, в каждой итерации он начинает поиск с last matched index:

Если ваш обычный экспресс-экспресс n использует флаг «g», вы можете использовать метод exec() несколько раз, чтобы найти последовательные совпадения в одной строке. Когда вы это сделаете, поиск начинается с подстроки str, заданной свойством lastIndex регулярного выражения (test() также увеличивает свойство lastIndex).

В вашем случае это намного проще и чище использовать String.prototype.replace метод:

var input = "{{ %[email protected] }}/{{ %[email protected] }} ({{ %[email protected] }}) {{ %[email protected] }} {{ %[email protected] }} {{ %1$d }} {{ %[email protected] }} of {{ %2$d }} of {{ %3$d }}"; 
 

 
var regex = /(\{\{ %(\d)\$(.) \}\})/g; 
 

 
input = input.replace(regex, '%@$2'); 
 

 
alert(input);

+0

Мне нужно преобразовать каждую из разных строк форматирования заполнителя с помощью js-совместимой версии, поэтому мне нужно сопоставить различные параметры. – chris

+0

На первый взгляд я пропустил, что '$ 2' в' replace (regex, '% @ $ 2') 'был для второго совпадения. Это хорошо работает. – chris

3

Это происходит потому, что вы измените переменную input в то время как exec не закончил. Индекс продвигается вперед, но строка становится короче.

Добавить еще одну переменную, или завернуть в отдельную функцию, или использовать replace как предложено @dfsq:

var input = "{{ %[email protected] }}/{{ %[email protected] }} ({{ %[email protected] }}) {{ %[email protected] }} {{ %[email protected] }} {{ %1$d }} {{ %[email protected] }} 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);

+0

Ах, что имеет смысл, почему все происходит. – chris

0

Сначала я предлагаю, чтобы удалить ненужные группы в регулярном выражении,

/\{\{ %(\d)\$. \}\}/g вместо от /(\{\{ %(\d)\$(.) \}\})/g. Затем, чтобы заменить вы можете использовать более короткий подход (а также более ясно, на мой взгляд):

var input = "{{ %[email protected] }}/{{ %[email protected] }} ({{ %[email protected] }}) {{ %[email protected] }} {{ %[email protected] }} {{ %1$d }} {{ %[email protected] }} of {{ %2$d }} of {{ %3$d }}"; 
var output = input.replace(/\{\{ %(\d)\$. \}\}/g, "%@$1"); 

Окончательное значение выходе %@1/%@1 (%@2) %@1 %@1 %@1 %@1 of %@2 of %@3

+0

Дополнительные группы необходимы, просто не очевидны в сокращенной версии строки, которую я опубликовал. – chris

Смежные вопросы