正则表达式不匹配所有出现

时间:2017-09-18 09:54:07

标签: javascript regex string

我正在尝试匹配模板文字中的所有匹配项<% anything %>。 我的正则表达式设置如下所示。

process(template : string , data: Object) {
    let re = /<%([^%>]+)?%>/g, match;
    while (match = re.exec(template)) {
        template = template.replace(match[0], data[match[1]]);
    }
    return template;
}

如果我的模板看起来像这样

`<div class="tile">
        <span><%ENTRY_NUMBER%></span> 
        <span><%NAME%> , <%CLASS%> , <%GENDER%> , <%AGE%></span>
</div>`

它会匹配第一次出现就好了,然后继续选择备用事件。如果html标签内有一个匹配它可以正常工作,但是当我使用第二个span元素中的倍数时,它会错过交替出现。我认为它与&lt;和&gt;。

当我将这些事件与<>而不是像下面的逗号分开时,它可以正常工作。

<span><%NAME%> <> <%CLASS%> <> <%GENDER%> <> <%AGE%></span>

这样的结果

<span> john <> biology <> male <> 17 </span>

我已多次检查正则表达式,但无济于事。

2 个答案:

答案 0 :(得分:2)

问题在于re.lastIndex存储的值是template之前的值,但是由于您更改了template值,re.lastIndex不再正确对于修改后的字符串。

请参阅下面的简化示例:

let template = `<%ENTRY_NUMBER%><%NAME%><%CLASS%><%GENDER%><%AGE%>`;
let re = /<%(.+?)%>/g, match;
let data = { 'NAME':'John', 'CLASS':'A3', 'GENDER':'Male', 'AGE':'19' };
while (match = re.exec(template)) {
    console.log(re.lastIndex);
    template = template.replace(match[0], data[match[1]]);
    console.log(template);
}
console.log(template);

// Iteration 1: re.lastIndex = 16
// undefined<%NAME%><%CLASS%><%GENDER%><%AGE%>
// Index is now between <%NAME% and > -> this match will be skipped
// and so on...

因此,最好在替换回调中动态修改字符串,因为一旦找到它们就会替换所有匹配项,并且您不必跟踪索引的搜索位置。

使用

process(template : string , data: Object) {
    return template.replace(/<%(.+?)%>/g, function($0, $1) { 
              return data[$1] ? data[$1] : $0; 
           });
}

请注意,<%(.+?)%>匹配<%,然后捕获除换行符之外的任何1个或多个字符,尽可能少地进入第1组,然后匹配%>。这样,您还会匹配包含%>的值(如果data包含此类密钥,则非常重要。)

答案 1 :(得分:0)

问题是你不需要全局标记g,因为你反复重复执行表达式,直到不匹配,但是多行标记m

&#13;
&#13;
let s = `<div class="tile">
        <span><%ENTRY_NUMBER%></span> 
        <span><%NAME%> , <%CLASS%> , <%GENDER%> , <%AGE%></span>
</div>`;
const re = /<%([^\%]+)?%>/,
  data = {
    ENTRY_NUMBER: '1977',
    NAME: 'Blue',
    CLASS: 'Vertebrates',
    GENDER: 'Male',
    AGE: '40'
  };


let k = 0;
while (re.test(s) && k++ < 1000) {
  match = re.exec(s);
  if (match) s = s.replace(match[0], data[match[1]]);
}
console.log(s);
&#13;
&#13;
&#13;