如何使用C#正则表达式替换/删除所有HTML标记,包括尖括号?
有人可以帮我提供代码吗?

评论

------- stackoverflow.com/a/1732454/961234

您没有指示它,但我推断您还想完全删除脚本和样式元素,而不仅仅是删除标签。下面的HTML Agility Pack答案对于删除标记是正确的,但是要删除脚本和样式,您还需要诸如stackoverflow.com/questions/13441470/…之类的东西。
表示为重复项的问题有很多信息(还有Tony the Pony!),但是它只要求打开标签,而不是所有标签。所以我不确定从技术上讲它是重复的。也就是说,答案是一样的:不。

#1 楼

如前所述,您不应使用正则表达式来处理XML或HTML文档。它们不能很好地处理HTML和XML文档,因为无法以一般方式表达嵌套结构。

可以使用以下内容。

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);


在大多数情况下都可以使用,但是在某些情况下(例如,包含尖括号的CDATA)将无法正常使用。

评论


这是一个幼稚的实现。.不幸的是,
”>是有效的html。虽然处理大多数理智的情况。

– Ryan Emerle
09年4月25日在0:38

如上所述,我知道在某些情况下此表达式将失败。我什至不确定一般情况是否可以由任何正则表达式正确处理。

–丹尼尔·布鲁克纳(DanielBrückner)
09年4月25日在0:49

不,这在所有情况下都会失败!它的贪婪。

–杰克
09年4月25日在1:04

@Cipher,您为什么认为贪婪是一个问题?假设匹配从有效HTML标记的开头开始,那么它将永远不会超出该标记的结尾。这就是[^>]的目的。

–艾伦·摩尔
09年4月25日在1:37

@AlanMoore html不是“常规语言”,即您无法正确地将所有有效html与正则表达式匹配。参见:stackoverflow.com/questions/590747/…

– Kache
2012年3月14日22:36

#2 楼

正确的答案是不要这样做,请使用HTML Agility Pack。

编辑添加:

为了让jesse无耻地窃取下面的评论,并避免被被指责在所有这些时间后都没有充分回答问题,这是一个使用HTML Agility Pack的简单,可靠的代码段,该代码段甚至可以用于格式最不完整,反复无常的HTML代码:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());


使用正则表达式解析HTML的情况很少,因为没有上下文感知就无法正确解析HTML,即使在非传统的正则表达式引擎中也很难提供上下文感知。您可以使用RegEx做到这一点,但是您需要手动进行验证。

Html Agility Pack可以为您提供强大的解决方案,从而减少了手动修复可能导致畸变的需求天真地将HTML视作与上下文无关的语法而导致的结果。如果您能找到比HTML Agility Pack更好/更快的解析器,那就去吧,但请不要让世界遭受更多破碎的HTML黑客攻击。

评论


HTML Agility Pack不能解决与使用HTML相关的所有问题(例如,如果您只想使用HTML代码的片段怎么办?!)。

–PropellerHead
09-10-23在7:23

它可以很好地与HTML片段配合使用,并且是原始海报描述的方案的最佳选择。另一方面,正则表达式只能与理想化的HTML一起使用,并且会与完全有效的HTML一起使用,因为HTML的语法不规则。如果他使用的是Ruby,我仍然会建议使用nokogiri或hpricot或Python的beautifulsoup。最好将HTML像HTML一样对待,而不是一些没有语法的任意文本流。

–JasonTrue
09-10-23在15:54

HTML不是常规语法,因此不能仅使用常规表达式进行解析。您可以将正则表达式用于词法分析,但不能用于语法分析。真的就是这么简单。语言学家在HTML甚至还没有存在之前就已经对此达成共识。

–JasonTrue
2011-3-15在15:43

这不是意见问题。正则表达式在大多数情况下可以为您提供大部分所需的信息,但是在非常常见的情况下它将失败。如果您能找到比HTML Agility Pack更好/更快的解析器,那就去吧,但请不要让世界遭受更多破碎的HTML骇客攻击。

–JasonTrue
2011-3-15在15:52

You can't correctly identify HTML tags reliably without parsing HTML. Do you understand all of the grammar for HTML? See the evil hack to get "pretty close" that other answers suggest, and tell me why you'd want to have to maintain that. Downvoting me because a hacky quick attempt works for your sample input isn't going to make your solution correct. I've occasionally used regexes the generate reports from HTML content or to fix up some CSS reference using negative matching on > to limit the chance of errors, but the we did additional verifications; it wasn't general purpose.

– JasonTrue
Dec 16 '11 at 9:13

#3 楼

这个问题太广泛了,无法确切地回答。您是在谈论从真实的HTML文档(例如网页)中删除所有标签吗?如果是这样,则必须:


删除<!DOCTYPE声明或<?xml prolog(如果存在)
删除所有SGML注释
删除整个HEAD element
删除所有SCRIPT和STYLE元素
用FORM和TABLE元素做Grabthar-知识-
删除其余标签
删除<![CDATA [and]]>序列CDATA部分中的内容,但不理会它们的内容

这只是我的脑海,我敢肯定还有更多。完成所有这些操作后,您最终将在某些地方同时使用单词,句子和段落,而在其他地方则得到了一大堆无用的空白。

但是,假设您只用一个片段,而只需删除所有标签就可以摆脱困境,这是我要使用的正则表达式:

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"


用单引号和双引号匹配它们自己的替代项就足以解决属性值中尖括号的问题。我认为不需要显式地匹配标记中的属性名称和其他内容,就像Ryan的答案中的regex一样。第一个替代方法可以解决所有这些问题。

如果您想知道这些(?>...)构造,它们就是原子团。它们使regex效率更高一些,但是更重要的是,它们防止了失控的回溯,当您像我一样混合使用交替词和嵌套量词时,应始终注意这一点。我真的不认为这会是一个问题,但是我知道如果我不提的话,其他人也会这样做。 ;-)

这个正则表达式当然并不完美,但是它可能和您需要的一样好。

评论


到目前为止,这是最好的答案。您回答发布者的问题,并解释为什么对给定任务不应使用正则表达式。做得好。

– JWilliams
2012年1月27日17:52

#4 楼

Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);


来源

#5 楼

@JasonTrue是正确的,不应通过正则表达式来剥离HTML标签。

使用HtmlAgilityPack剥离HTML标签非常简单:

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}


评论


尽管对此我有些迟了,但我想提一下,它也适用于Word和其他办公产品产生的xml。任何曾经需要处理Word xml的人都可以很好地使用它,因为它确实有很大帮助,特别是如果您需要从内容中剥离标签,而这正是我所需要的。

–史蒂夫·佩蒂弗(Steve Pettifer)
13年4月9日在8:18

当所有其他方法似乎都失败了时,这个简单的代码片段挽救了这一天。谢谢!

– Ted Krapf
3月6日3:49

#6 楼

我想回覆Jason的回应,尽管有时您需要天真地解析一些HTML并提取文本内容。

我需要使用由富文本编辑器创建的一些HTML来做到这一点,并且总是很有趣。

在这种情况下,您可能需要删除某些标签的内容以及标签本身。

就我而言,标签被扔进了这种混合物中。某些人可能会发现我的(很少)天真的实现是一个有用的起点。

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }


评论


除了明显的跨平台换行问题之外,对内容进行定界时,使用不合要求的量词也很慢。将诸如。*(?!之类的内容与RegexOptions.SingleLine修饰符一起用于前两个,而将<[^>] *>用于最后一个。还可以通过捕获的第一个标签名称的替换以及在否定的超前标签和最终标签中的反向引用来组合第一个标签。

– ChristF
13年5月9日23:38



#7 楼

请尝试在此URL上使用正则表达式方法:http://www.dotnetperls.com/remove-html-tags


/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}


#8 楼

用这个..

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"


#9 楼

.+?中添加<[^>]*>并尝试使用此正则表达式(基于此):

<[^>].+?>


c#.net regex演示


#10 楼

使用此方法删除标签:

public string From_To(string text, string from, string to)
{
    if (text == null)
        return null;
    string pattern = @"" + from + ".*?" + to;
    Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    MatchCollection matches = rx.Matches(text);
    return matches.Count <= 0 ? text : matches.Cast<Match>().Where(match => !string.IsNullOrEmpty(match.Value)).Aggregate(text, (current, match) => current.Replace(match.Value, ""));
}