【问题标题】:Regular expression to remove HTML tags删除 HTML 标签的正则表达式
【发布时间】:2011-04-16 23:34:41
【问题描述】:

我正在使用以下正则表达式从字符串中删除 html 标记。它可以工作,除非我留下结束标签。如果我尝试删除:<a href="blah">blah</a>,它会留下<a/>

我根本不知道正则表达式的语法,并且摸不着头脑。有RegEx知识的人可以给我一个可行的模式吗?

这是我的代码:

  string sPattern = @"<\/?!?(img|a)[^>]*>";
  Regex rgx = new Regex(sPattern);
  Match m = rgx.Match(sSummary);
  string sResult = "";
  if (m.Success)
   sResult = rgx.Replace(sSummary, "", 1);

我希望删除第一次出现的 &lt;a&gt;&lt;img&gt; 标签。

【问题讨论】:

  • 字符串前后的样本会有所帮助
  • “我正在使用 ... 正则表达式来删除 html 标签”这是你的问题。请改用 HTML 解析器。
  • RegEx match open tags except XHTML self-contained tags 的可能副本——尽管有标题,这完全是一个骗局。承诺。
  • 由于其他人看不到可能的用例,这是我的... a) 在代码沙箱 (Salesforce) 中工作,即使不是不可能,也很难包含和维护一个 3rd-party 库 b) 仅尝试从电子邮件正文中删除标签以获得更清晰的电子邮件到案例描述(即 - 不涉及安全问题) c) stripHtmlTags() 方法没有做足够的工作来删除额外的标签

标签: c# .net regex


【解决方案1】:

使用正则表达式解析 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 标签。
  • @Tony,修复了正则表达式中的一个错误。现在应该编译
  • 谢谢,我去看看。
【解决方案2】:

转这个:

'<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();
}

【讨论】:

  • 这是一个很好的答案,如果您想删除所有标签,包括标签的文本内容,您将如何更改它?只是留下不在标签内的文本?
  • 啊,我想通了,我想出了:function removeTags(string){ return string.replace(/]*>.*?(]*>) ?/g, ' ') .replace(/\s{2,}/g, ' ') .trim(); }
  • 这很容易被破坏,不应该出于任何原因使用。如果你真的想要清理 HTML , 使用真正了解 HTML 语法的东西。试试这个输入,它加载一个 1px 的 GIF,然后假设 jQuery 存在,加载一个脚本:&lt;img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAA‌​QABAAACAkQBADs=" onload="$.getScript('evil.js');1&lt;2&gt;3"&gt;。它不会正确删除该元素,即使它应该这样做。
  • 以赛亚,你警告的“任何原因”部分不太适合这个问题。使用正则表达式从字符串中删除某些东西对我来说听起来像是一个非常受控的环境。如果任务是像您的示例所暗示的那样进行内容抓取或更动态的操作,我同意解决方案不是一些即兴的正则表达式。这是一篇关于“bazillion different packages”的文章。
【解决方案3】:

为了同时删除标签之间的空格,您可以使用以下方法在输入 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 之前或之后的空格: “   测试文本   测试 1         测试 2      测试 3”。

请注意test text 之前的空格来自&lt;del&gt; test text &lt;/del&gt; html,test 3 之后的空格来自&lt;em&gt;&lt;span style="text-decoration:underline;background-color:#006600;"&gt; test 3 &lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; html。

【讨论】:

    【解决方案4】:

    剥离 HTML 元素(带/不带属性)

    /<\/?[\w\s]*>|<.+[\W]>/g
    

    这将剥离所有 HTML 元素并留下文本。这甚至适用于格式错误的 HTML 元素(即缺少结束标签的元素)

    Reference and example(例 10)

    【讨论】:

    • 这对我有帮助。如果我需要搜索/替换特定标签怎么办?喜欢跨度?
    • 对于定位跨度标签,您可以修改接受的答案以满足您的需要或使用 /&lt;\/?[span]*&gt;|&lt;.+[\W]&gt;/g
    • 正则表达式也匹配 &lt;p&gt;&lt;/p&gt; 标签。
    • 哦,是的,你是对的。 cmets 中给出的正则表达式有一个小错误,这也会导致它匹配所有&lt;a&gt; 标签。要纠正,您需要做的就是删除单词 span 周围的方括号。即 /&lt;\/?span*&gt;|&lt;.+[\W]&gt;/g
    • 这在&lt;h2 class="ofscreen"&gt;Webontwikkeling leren&lt;/h2&gt;&lt;h1&gt;Regular Expressions&lt;/h1&gt;&lt;p&gt;"Alle onderdelen van MDN (documenten en de website zelf) worden gemaakt door een open gemeenschap."&lt;/p&gt;&lt;br/&gt; 上失败,它选择了整个字符串。
    【解决方案5】:

    所以大家说的HTML解析器是Html Agility Pack

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

    【讨论】:

      【解决方案6】:

      可以使用:

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

      【讨论】:

        【解决方案7】:

        如果您只需要查找开始标签,您可以使用以下正则表达式,它将标签类型捕获为 $1(a 或 img),并将内容(包括结束标签,如果有的话)捕获为 $2:

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


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

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

        基本上,您只需要在上述正则表达式之一上使用替换功能,然后返回 $2 即可获得您想要的。

        关于查询的简短说明:

        • ( ) - 用于捕获与括号内的正则表达式匹配的任何内容。捕获的顺序为:$1、$2 等。
        • ?: - 在左括号“(”之后使用,用于不捕获括号内的内容。
        • \1 - 正在复制捕获号 1,这是标记类型。我必须捕获标签类型,以便结束标签与开始标签一致,而不是像:&lt;img src=""&gt; &lt;/a&gt;
        • \s - 是空格,因此在打开标签&lt;img 后至少会有1 个空格以防有属性(例如,它不会匹配&lt;imgs&gt;)。
        • [^&gt;]* - 正在寻找除内部字符之外的任何内容,在本例中为 &gt;* 表示无限次。
        • ?! - 正在寻找除内部字符串之外的任何内容,有点类似于 [^&gt;] 只是用于字符串而不是单个字符。
        • [\s\S] - 几乎与. 一样使用,但允许任何空格(如果标签之间有新行,空格也会匹配)。如果您使用的是正则表达式“s”标志,那么您可以改用.

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

        不使用结束标签的例子: https://regex101.com/r/MGmzrh/2


        Regex101 对我所做的也有一些解释:)

        【讨论】:

          【解决方案8】:

          您可以使用现有的库来去除 html 标签。一个很好的是Chilkat C# Library

          【讨论】:

          • 这一切都很好,但我不仅需要删除标签,还需要删除标签之间的所有内容。
          【解决方案9】:

          如果你只是想删除标签(而不知道结束标签在哪里),我真的不知道为什么人们对此如此担忧。

          这个正则表达式似乎可以处理任何我可以扔给它的东西:

          &lt;([\w\-/]+)( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* *&gt;

          分解:

          • &lt;([\w\-/]+) - 匹配开始或结束标签的开头。如果你想处理无效的东西,你可以在这里添加更多
          • ( +[\w\-]+(=(('[^']*')|("[^"]*")))?)* - 该位匹配属性 [0, N] 次(* 结束)
            • +[\w\-]+ - 是空格,后跟属性名称
            • (=(('[^']*')|("[^"]*")))? - 并非所有属性都有赋值 (?)
              • ('[^']*')|("[^"]*") - 在具有赋值的属性中,值是带有单引号或双引号的字符串。不允许跳过结束语以使事情正常进行
          • *&gt; - 整个内容以任意数量的空格结尾,然后是右括号

          显然,如果有人向它抛出超级无效的 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>

          【讨论】:

            【解决方案10】:

            从字符串中删除图片,在c#中使用正则表达式(通过图片id进行图片搜索)

            string PRQ=<td valign=\"top\" style=\"width: 400px;\" align=\"left\"><img id=\"llgo\" src=\"http://test.Logo.png\" alt=\"logo\"></td>
            
            var regex = new Regex("(<img(.+?)id=\"llgo\"(.+?))src=\"([^\"]+)\"");
            
            PRQ = regex.Replace(PRQ, match => match.Groups[1].Value + "");
            

            【讨论】:

              【解决方案11】:

              为什么不尝试不情愿的量词? htmlString.replaceAll("&lt;\\S*?&gt;", "")

              (虽然是Java,但主要是展示想法)

              【讨论】:

                【解决方案12】:

                简单的方法,

                String html = "<a>Rakes</a> <p>paroladasdsadsa</p> My Name Rakes";
                
                html = html.replaceAll("(<[\\w]+>)(.+?)(</[\\w]+>)", "$2");
                
                System.out.println(html);
                

                【讨论】:

                  【解决方案13】:

                  这是我已经使用了一段时间的扩展方法。

                  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;
                       }
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    这段代码可以帮助您轻松删除任何 html 标签:

                    import re
                    string = str(<a href="blah">blah</a>)
                    replaced_string = re.sub('<a.*href="blah">.*<\/a>','',string) // remember, sub takes 3 arguments.
                    

                    输出是一个空字符串。

                    【讨论】:

                      【解决方案15】:

                      这是我使用简单的正则表达式创建的一个扩展方法,用于从字符串中删除 HTML 标记:

                      /// <summary>
                      /// Converts an Html string to plain text, and replaces all br tags with line breaks.
                      /// </summary>
                      /// <returns></returns>
                      /// <remarks></remarks>
                      [Extension()]
                      public string ToPlainText(string s)
                      {
                      
                          s = s.Replace("<br>", Constants.vbCrLf);
                          s = s.Replace("<br />", Constants.vbCrLf);
                          s = s.Replace("<br/>", Constants.vbCrLf);
                      
                      
                          s = Regex.Replace(s, "<[^>]*>", string.Empty);
                      
                      
                          return s;
                      }
                      

                      希望对您有所帮助。

                      【讨论】:

                      • 不只是
                        以斜线结尾;事实上,从技术上讲,任何元素都可以以斜杠结尾——它可能不一定在它后面或尾随一个或没有空格。这也是有效的:&lt;p / &gt;
                      • 如果需要,这些行只是为了保留换行符。否则,它们可能会被删除。
                      • 很好,你在哪里用这个?在公共网站上?输入 '
                      • Rei,它会移除

                        你还没测试过
                      • VirtualBlackFox,是的,我在公共网站上使用它,而且非常有效。 '
                      【解决方案16】:

                      选择除其中的内容以外的所有内容:

                      (?:<span.*?>|<\/span>|<p.*?>|<\/p>)
                      

                      【讨论】: