从html中删除href链接,该链接匹配使用正则表达式忽略内部链接标记的文本

时间:2014-01-30 13:09:25

标签: javascript regex google-apps-script

意识到所有SO answers that warn against Regex to parse html我有一个场景,其中解析器和DOM技巧是不可能的,并且需要使用正则表达式来删除具有已定义文本值的标记和内容。例如:

<div>foo bar</div
<a href="http://example.com">some text</a>
<div>foo bar foo bar</div> 

我目前正在使用此功能来解析匹配的链接

/**
 * Removes links from html text
 * @param {string} html The html to be cleaned.
 * @param {string} exclude The string of link text to remove.
 * @returns {string} Cleaned html.
 */
function cleanBody(html, exclude){
  html = html.replace(/\r?\n|\r|\t|/g, '');
  var re = '<a\\b[^>]*>('+exclude+')<\\/a>';
  return html.replace(new RegExp(re,'ig'),"");
}

在上面的例子中,我传递了html和字符串'some text'来删除它。这适用于我的场景,直到包含其他标记,例如

<div>foo bar</div
<a href="http://example.com"><font color="#1122cc">some text</font></a>
<div>foo bar foo bar</div> 

如何改进正则表达式(或函数)以考虑额外的标记(不使用DOM,jQuery或其他库)?

1 个答案:

答案 0 :(得分:1)

以下正则表达式适用于您提供的特定情况:

var re="<a\\b[^>]*>(<[^>]+>)*("+exclude+")(<(?!/a>)[^>]+>)*</a>";
  • 在打开锚标记的匹配后,添加一个匹配零个或多个标记的模式,无论它们是打开标记还是结束标记,有效还是无效:(<[^>]+>)*
  • 在匹配排除文本后,添加一个匹配零个或多个标签的模式,无论它们是打开标签还是关闭标签,有效还是无效,但是 - 使用否定前瞻 - 与结束锚标签不匹配:(<(?!/a>)[^>]+>)*

请注意这个正则表达式在其工作方式上仍然不是很“聪明”。它不会尝试匹配平衡标签或过滤无效的有效标签名称,因此将匹配以下无效HTML:

<a href="http://example.com">some text</font></span></div></a>
<a href="http://example.com"><div>some text</font></span></div></a>
<a href="http://example.com"><foo>some text</div></a>

此外,请注意,以下无效HTML与 仅匹配结束锚标记

<a href="http://example.com"><div>some text</font></a></div>

结束</div>将不匹配。

小心嵌套锚点。以下内容将匹配(注意只有 一个 关闭锚标记匹配):

<a href="http://foo.org"><a href="http://example.com">some text</a>

可能还有其他数据出乎意料地与我未曾想到过的模式相匹配。

在正面,嵌套标签不必包装排除文本。以下内容将匹配:

<a href="http://example.com"><span></span>some text<div></div></a>
<a href="http://example.com">some text<font></font></a>

有一些机会可以使正则表达式更灵活和/或更安全,但这超出了您所要求的范围。