【问题标题】:Regex not replacing all occurrences正则表达式不替换所有出现
【发布时间】:2017-11-26 13:28:42
【问题描述】:

我正在尝试使用以下代码替换所有出现的正则表达式搜索和替换,但由于某种原因它只替换了第一次出现:

var userContent = '<div class="header"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div><div class="footer"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div>';

var menuItems = "<li><a href='/'>Home</a></li><li><a href='/about'>About</a></li><li><a href='/portfolio'>Portfolio</a></li><li><a href='/contact'>Contact</a></li>";

var quote = function(str) {
    return str.replace(/([.?*+^$[\]/(){}|-])/g, "\\$1");
};

var re = new RegExp(quote('<!--Start Main Menu-->') + "[^]+" + quote('<!--End Main Menu-->'), 'g');
userContent = userContent.replace(re, '<!--Start Main Menu--><ul class="main-menu">' + menuItems + '</ul><!--End Main Menu-->');

console.log(userContent);

我似乎不明白为什么,我已经在引用 /g 中说明了,我尝试将 /g 添加到 userContent.replace 但它似乎不喜欢它。

小提琴: https://jsfiddle.net/xqt3kj7r/

【问题讨论】:

  • 用 HTML 解析正则表达式不是一个好主意。
  • @NisargShah 我知道,但在这种情况下,这是我正在处理的情况。如果它在一次出现时解析 HTML 很好,为什么不为两者都做呢?有没有更好的方法来做到这一点?
  • 您可以使用 Javascript 通过处理 DOM 元素来做到这一点。你能在问题中解释你想要做什么吗?
  • @NisargShah 我基本上是在尝试用变量 menuItems 替换 和 之间的所有内容。

标签: javascript regex


【解决方案1】:

您正在匹配 greedy,因此正则表达式在 first 出现的“开始主菜单”和 last 中占用了所有字符em> 出现“结束主菜单”。

需要的是非贪婪匹配。试试这个:

var userContent = '<div class="header"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div><div class="footer"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div>';

var menuItems = "<li><a href='/'>Home</a></li><li><a href='/about'>About</a></li><li><a href='/portfolio'>Portfolio</a></li><li><a href='/contact'>Contact</a></li>";

var quote = function(str) {
    return str.replace(/([.?*+^$[\]/(){}|-])/g, "\\$1");
};

var re = new RegExp(quote('<!--Start Main Menu-->') + "[^]*?" + quote('<!--End Main Menu-->'), 'g');
userContent = userContent.replace(re, '<!--Start Main Menu--><ul class="main-menu">' + menuItems + '</ul><!--End Main Menu-->');

console.log(userContent);

请注意 RE 如何从 + 更改为 *?。我不认为使用正则表达式来解决这个问题是一个好习惯,但这只是为了向您展示它是如何工作的。

【讨论】:

  • 这正是我想要的,谢谢!只是出于兴趣,有什么更好的方法来做到这一点?
  • 我会接受 Nisarg 的提议。当然,您需要对其进行调整以替换 所有 出现的主菜单,但我猜这可以解决。
【解决方案2】:

正如我在 cmets 中提到的,如果您希望为此处理 HTML,您可以选择 .header 类,并将其替换为 innerHTML 变量 menuItems 中的新 HTML。

在下面的 sn-p 中,我将变量 menuItems 包装在 ul 标记中,以确保当我们覆盖 div.header 内部的原始 ul 标记时,新的 li 标记具有ul 在他们身边。

另外,我修改了menuItems 中的li 之一,以表明该列表实际上正在被替换。

var userContent = '<div class="header"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div><div class="footer"><!--Start Main Menu--><ul class="main-menu"> <li><a href="/">Home</a> </li> <li><a href="/">About</a> </li> <li><a href="/">Portfolio</a> </li> <li><a href="/">Contact</a> </li> </ul><!--End Main Menu--></div>';

var menuItems = "<ul><li><a href='/'>Home</a></li><li><a href='/about'>About</a></li><li><a href='/portfolio'>Portfolio</a></li><li><a href='/contact'>Contact (new item)</a></li></ul>";

var placeholderDiv = document.getElementById("placeholder");

// Add the HTML to the placeholder Div.
placeholderDiv.innerHTML = userContent;

setTimeout(function() {
  // Now we need to replace the content inside the header element.
  // Select the children of #placeholder that have class "header"
  var headerElements = document.querySelectorAll("#placeholder div.header");

  if (headerElements.length > 0) {
    console.log("Replacing innerHTML");
    var header = headerElements[0];
    header.innerHTML = menuItems;
  }

}, 1000);
&lt;div id="placeholder"&gt;&lt;/div&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-19
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多