正则表达式删除HTML标签

28
我正在使用以下正则表达式从字符串中删除HTML标签。它有效,但我忘记了关闭标签。如果我尝试删除:<a href="blah">blah</a>,它会留下<a/>
我完全不了解正则表达式语法,并且只是凭经验摸索出这个方法。请有正则表达式知识的人提供一个可行的模式。
以下是我的代码:
  string sPattern = @"<\/?!?(img|a)[^>]*>";
  Regex rgx = new Regex(sPattern);
  Match m = rgx.Match(sSummary);
  string sResult = "";
  if (m.Success)
   sResult = rgx.Replace(sSummary, "", 1);
我想要移除第一个出现的 <a><img> 标签。

一个示例的“before”和“after”字符串会有所帮助。 - Steve Ellinger
15
我正在使用正则表达式删除HTML标签,但这是存在问题的。建议你使用HTML解析器来处理。 - Welbog
1
可能是RegEx匹配除XHTML自包含标签外的开放标签的重复问题--尽管标题如此,但这是一个完全相同的问题。我保证。 - egrunin
5
必要的链接是必要的。 - Femaref
由于其他人可能看不到这个的潜在用途,这里是我的想法: a)在代码沙盒(Salesforce)中工作时,很难甚至不可能包含和维护第三方库 b)仅尝试从电子邮件正文中剥离标记,以获得更清晰的电子邮件到案例描述(即-没有安全问题涉及) c)stripHtmlTags()方法未能完全删除额外的标记 - Ixalmida
在我看来,这个问题有更好的答案:https://dev59.com/LWgu5IYBdhLWcg3wkH6P - tommy.carstensen
17个回答

28

为了将此转换为:

'<td>mamma</td><td><strong>papa</strong></td>'

变成这样:

'mamma papa'

你需要用空格替换标签:

.replace(/<[^>]*>/g, ' ')

并将任何重复的空格缩减为单个空格:

.replace(/\s{2,}/g, ' ')

然后使用以下方法删除前导和尾随空格:

.trim();

这意味着您的删除标签功能应该如下所示:

function removeTags(string){
  return string.replace(/<[^>]*>/g, ' ')
               .replace(/\s{2,}/g, ' ')
               .trim();
}

这是一个很好的答案,如果您想剥离所有标签,包括标签内的文本内容,您会如何修改它?只留下不在标签内的文本? - user280109
2
啊哈!我想到了,我写出了以下代码:function removeTags(string){ return string.replace(/<[^>]>.?(<[^>]*>)?/g, ' ') .replace(/\s{2,}/g, ' ') .trim(); } - user280109
4
这个东西太容易被破解了,不应该因为任何原因而使用。如果你真的想要净化HTML,请使用能够理解HTML语法的工具。试一下这个输入,它会加载一个1像素的GIF图像,然后假设jQuery存在,会加载一个脚本:<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAA‌​QABAAACAkQBADs=" onload="$.getScript('evil.js');1<2>3">。即使它应该可以,它也无法正确地移除该元素。 - Claudia
1
Isiah,“任何原因”警告的部分似乎不太适合这个问题。 对我来说,使用正则表达式从字符串中删除某些内容听起来像是一个非常受控制的环境。 如果任务是做内容抓取或者像你的例子所示的更动态的事情,我同意解决方案不是一些改进的正则表达式。 这里有一篇关于“无数不同包”的文章作为开始。 - Johs

26

使用正则表达式解析HTML存在很多问题。由于HTML不是一种正则语言,因此无法使用正则表达式进行100%的正确解析。这只是你将遇到的许多问题之一。最好的方法是使用HTML / XML解析器来代替。

以下是我之前写的一篇博客文章,详细介绍了这个问题。

话虽如此,以下是一个解决该特定问题的方案。然而,这绝不是完美的解决方案。

var pattern = @"<(img|a)[^>]*>(?<content>[^<]*)<";
var regex = new Regex(pattern);
var m = regex.Match(sSummary);
if ( m.Success ) { 
  sResult = m.Groups["content"].Value;

Jared,当我尝试时,似乎会抛出异常。而且,这会将标记之间的文本删除吗?我想从字符串中删除第一个出现的a、p和img标记。 - LilMoke
@Tony,修复了正则表达式中的一个错误。现在应该可以编译了。 - JaredPar

8
为了删除标签之间的空格,您可以使用以下方法,它是正则表达式和修剪输入html开头和结尾空格的组合:
    public static string StripHtml(string inputHTML)
    {
        const string HTML_MARKUP_REGEX_PATTERN = @"<[^>]+>\s+(?=<)|<[^>]+>";
        inputHTML = WebUtility.HtmlDecode(inputHTML).Trim();

        string noHTML = Regex.Replace(inputHTML, HTML_MARKUP_REGEX_PATTERN, string.Empty);

        return noHTML;
    }

以下是需要翻译的内容:

对于以下输入:

      <p>     <strong>  <em><span style="text-decoration:underline;background-color:#cc6600;"></span><span style="text-decoration:underline;background-color:#cc6600;color:#663333;"><del>   test text  </del></span></em></strong></p><p><strong><span style="background-color:#999900;"> test 1 </span></strong></p><p><strong><em><span style="background-color:#333366;"> test 2 </span></em></strong></p><p><strong><em><span style="text-decoration:underline;background-color:#006600;"> test 3 </span></em></strong></p>      

输出的内容仅为文本,没有HTML标签之间的空格或HTML标签前后的空格: " test text test 1 test 2 test 3"。
请注意,test text前面的空格来自于HTML标签<del> test text </del>,而test 3后面的空格来自于HTML标签<em><span style="text-decoration:underline;background-color:#006600;"> test 3 </span></em></strong></p>

4
去除HTML元素(带/不带属性)
/<\/?[\w\s]*>|<.+[\W]>/g

这将删除所有的HTML元素,只留下文本。即使是格式不正确的HTML元素(即缺少闭合标签的元素),也能很好地工作。 参考和示例(Ex.10)

1
这对我很有帮助。如果我需要搜索/替换特定标签,比如span标签呢? - GaryP
1
针对span标签的定位,您可以修改接受的答案以适应您的需求,或使用 **/<\/?[span]*>|<.+[\W]>/g**。 - Niket Pathak
1
哦,是的,你说得对。在注释中给出的正则表达式中有一个小错误,这也会导致它匹配所有的<a>标签。要纠正这个问题,你只需要删除单词span周围的方括号即可。即:**/<\/?span>|<.+[\W]>/g** - Niket Pathak
可以通过将表情符号放入HTML标记中来避免这种情况,因此如果您正在处理Unicode字符串,则不是一个好主意。 <(.|\\n)*?> 不会受到这种弱点的影响。 - Mattis
你有示例吗?我尝试了 <a href="xyz.com">Aan deU+1F600 slag</a>,对我来说运行良好。 - Niket Pathak
显示剩余3条评论

3
如果您需要仅查找开放标签,则可以使用以下正则表达式,它将捕获标签类型为$1(a或img),内容(包括关闭标签(如果有))为$2:
(?:<(a|img)(?:\s[^>]*)?>)((?:(?!<\1)[\s\S])*)


如果您还有关闭标签,您应该使用以下正则表达式,它将捕获标签类型作为$1(a或img),内容作为$2:

(?:<(a|img)(?:\s[^>]*)?>)\s*((?:(?!<\1)[\s\S])*)\s*(?:<\/\1>)

基本上你只需要在以上正则表达式中使用replace函数,并返回$2,就能得到你想要的内容。
查询的简短解释:
  • ( ) - 用于捕获与括号内的正则表达式匹配的任何内容。捕获的顺序是 $1,$2 等。
  • ?: - 在开括号“(”后用于不捕获括号内的内容。
  • \1 - 复制捕获号码 1,即标记类型。我必须捕获标记类型,以便关闭标记与打开标记一致,而不是像这样:<img src=""> </a>
  • \s - 是空格,因此在打开标记 <img 后,如果有属性,则至少会有 1 个空格(因此它不会匹配例如 <imgs>)。
  • [^>]* - 查找除括号内字符外的任何内容,该字符在本例中为 >* 表示无限次数。
  • ?! - 查找除字符串内部之外的任何内容,有点类似于 [^>],只是针对字符串而不是单个字符。
  • [\s\S] - 几乎像. 但允许任何空格(也将匹配标记之间存在换行符的情况)。如果使用正则表达式 "s" 标志,则可以使用 .

使用带有结束标记的示例: https://regex101.com/r/MGmzrh/1

使用不带结束标记的示例: https://regex101.com/r/MGmzrh/2


Regex101还对我所做的事情进行了一些解释 :)


3

大家谈论的HTML解析器是Html Agility Pack

如果是干净的XHTML,您还可以使用System.Xml.Linq.XDocumentSystem.Xml.XmlDocument


3

可以使用:

Regex.Replace(source, "<[^>]*>", string.Empty);

2
你可以使用已经存在的库来去除HTML标签。其中一个很好的库是Chilkat C# Library

这很好,但我不仅需要删除标签,还需要删除标签之间的所有内容。 - LilMoke

2
如果你只是想删除标签(而不是找出结束标签在哪里),我真的不知道为什么人们如此紧张。这个正则表达式似乎可以处理我能想到的任何东西:
``` <([\w\-/]+)( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* *> ```
解释如下:
- `<([\w\-/]+)`:匹配开头的开始或结束标签,如果你想处理无效的内容,你可以在这里添加更多。 - `( +[\w\-]+(=(('[^']*')|("[^"]*")))?)*`:这部分匹配属性[0,N]次(在结尾处使用 `*`)。 - `+[\w\-]+`:空格后跟属性名称。 - `(=(('[^']*')|("[^"]*")))?`:并非所有属性都有赋值(使用 `?`)。 - `('[^']*')|("[^"]*")`:对于具有赋值的属性,其值是带有单引号或双引号的字符串。不能跳过闭合引号以使其工作。 - `*>`:整个结束于任意数量的空格,然后是关闭括号。
显然,如果有人向它投入超级无效的 HTML,则会出现问题,但对于我想到的任何有效内容都有效。在这里测试一下吧:

const regex = /<([\w\-/]+)( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* *>/g;

const byId = (id) => document.getElementById(id);

function replace() {
console.log(byId("In").value)
  byId("Out").innerText = byId("In").value.replace(regex, "CUT");
}
Write your html here: <br>
<textarea id="In" rows="8" cols="50"></textarea><br>
<button onclick="replace()">Replace all tags with "CUT"</button><br>
<br>
Output:
<div id="Out"></div>


不支持自引用标签。 - Kunal Mukherjee

1

这是我已经使用了相当长时间的扩展方法。

public static class StringExtensions
{
     public static string StripHTML(this string htmlString, string htmlPlaceHolder) {
         const string pattern = @"<.*?>";
         string sOut = Regex.Replace(htmlString, pattern, htmlPlaceHolder, RegexOptions.Singleline);
         sOut = sOut.Replace("&nbsp;", String.Empty);
         sOut = sOut.Replace("&amp;", "&");
         sOut = sOut.Replace("&gt;", ">");
         sOut = sOut.Replace("&lt;", "<");
         return sOut;
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接