2017-01-23 78 views
0

我试图做一个快速和脏的模板测试,但当正则表达式替换时,它只替换最后一次出现,我认为\g将替换所有副本。但它只匹配最后一次出现。正则表达式全局替换不替代第一次出现

How to String.match() distinct it ${SOME_TEXT} using Regex

我试图做的是提示用户每进行一次独特的变量名。

Title = t 
name = n 
result = '${Title} - n - t' 

使用/\$\{([^\}]+)\}/g作品,但用户多次提示。

Title = t 
name = n 
Title = t 
result = 't - n - t' 

那么我怎样才能用一个值代替每个标记,无论它出现多少次。

<html> 
<head> 
    <script type="application/javascript"> 

     window.copyToClipboard = function(n) { 
      var u = "_hiddenCopyText_", t, i, r; 
      t = document.getElementById(u); 
      t.textContent = n; 
      i = document.activeElement; 
      t.focus(); 
      t.setSelectionRange(0, t.value.length); 
      try { 
       r = document.execCommand("copy") 
      } catch (f) { 
       r = !1 
      } 
      return i && typeof i.focus == "function" && i.focus(), 
       t.textContent = "", 
       r 
     }; 
     //${varname} 
     window.templateRegex = /\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g; 
     window.test = " ${Title} - ${Name} - ${Title}" 
     window.copyTemplate = function (template) { 
      var result = template.replace(window.templateRegex, function(match, token){ 
       return window.prompt("replace value for ${"+token+"}","${"+token+"}"); 
      }); 
      window.copyToClipboard(result); 
     }; 

    </script> 
</head> 
<textarea id="_hiddenCopyText_"></textarea> 
<button onclick="copyTemplate(window.test)">Test</button> 
</html> 

的jsfiddlehttps://jsfiddle.net/ksu37c3b/

回答

1

如果相同${..}($ {Title})发生多次,则/\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g只会匹配最后一个。要匹配所有元素,/\$\{([^\}]+)\}/g将起作用,它不需要负向预览(?![\S\s]*\$\{\1\})
在字符串"${Title} - ${Name} - ${Title}"中,只有${Name}${Title}匹配该模式,因为第一个和最后一个是相同的,如果更改该字符串,例如"${Title2} - ${Name} - ${Title}"它将匹配所有元素,因为$ {Title2}和$ {Title}不相等。这就是(?![\S\s]*\$\{\1\})试图做的,如果最后${..}和当前${..}是相同的,它将不匹配。

更新

所以,我怎么可以替换单个值每个令牌不管出现多少次。

可以使用match()方法来获得令牌的数组发生,然后通过一个更换一个,下面的代码将工作:

window.templateRegex = /\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g; 
 
window.test = " ${Title} - ${Name} - ${Title}"; 
 
var userinput, reg, i; 
 
var arr = window.test.match(/\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g); 
 
for (i = 0; i < arr.length; i++) { 
 
    arr[i] = arr[i].replace(/[\$\{\}]/g, ""); 
 
    userinput = window.prompt("replace value for " + arr[i]); 
 
    reg = new RegExp("\\$\\{" + arr[i] + "\\}", 'g'); 
 
    console.log(reg); 
 
    window.test = window.test.replace(reg, userinput); 
 
} 
 
alert(window.test);

我已修改了代码如下:

window.copyToClipboard = function(n) { 
 
    var u = "_hiddenCopyText_", 
 
    t, i, r; 
 
    t = document.getElementById(u); 
 
    t.textContent = n; 
 
    //** snip **// 
 
}; 
 
//${varname} 
 
window.templateRegex = /\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g; 
 
window.test = " ${Title} - ${Name} - ${Title}"; 
 
window.copyTemplate = function(template) { 
 
    var result = template; 
 
    var userinput, reg; 
 
    var arr = result.match(/\$\{([^\}]+)\}(?![\S\s]*\$\{\1\})/g); 
 
    for (let i = 0; i < arr.length; i++) { 
 
     arr[i] = arr[i].replace(/[\$\{\}]/g, ""); 
 
     userinput = window.prompt("replace value for " + arr[i]); 
 
     reg = new RegExp("\\$\\{" + arr[i] + "\\}", 'g'); 
 
     console.log(reg); 
 
     result = result.replace(reg, userinput); 
 
    } 
 
    window.copyToClipboard(result); 
 
};
<textarea id="_hiddenCopyText_"></textarea> 
 
<button onclick="copyTemplate(window.test)">Test</button>​

+0

提示3次,不是两次。 –

+0

@Ryan The Leach我更新了我的答案,上面的代码提示2次。 –

0

这应该做你想做的/\$\{([^\}]+)\}(?![\S\s]\$\{\1\})/

我只是删除在未来的负面看中间的*,因为它是导致它相匹配的最终发生的每时间。

+0

这样做的结果是“T - $ {Name} - $ {Title}” –

+0

我必须复制它错误。去除星星会产生3个提示,一个用于标题,一个用于名称,一个用于标题。我想要做的是提供一个标题提示和一个提示名称。 –

+0

为什么不只是拿回来的东西,看一下匹配结果的数组,并检查是否有任何重复?然后,您可以提示尚未提示的匹配项。 如果您在接下来的3个小时内无法弄清楚,我会在3小时内完成工作后对其进行更深入的研究。 – Zei