特定标签及其内容的正则表达式,按标签名称分组

Posted

技术标签:

【中文标题】特定标签及其内容的正则表达式,按标签名称分组【英文标题】:Regex for specifig tags and their content, groupped by the tag name 【发布时间】:2010-09-17 01:31:25 【问题描述】:

这是输入(html,不是 xml):

... html content ...
<tag1> content for tag 1 </tag1>
<tag2> content for tag 2 </tag2>
<tag3> content for tag 3 </tag3>
... html content ...

我想获得 3 场比赛,每场比赛有两组。第一组将包含标签的名称,第二组将包含标签的内部文本。只有这三个标签,所以它不需要是通用的。

换句话说:

match.Groups["name"] would be "tag1"
match.Groups["value"] would be "content for tag 2"

有什么想法吗?

【问题讨论】:

注意更新的 HtmlAgilityPack 示例;我怀疑这可以满足您的需要。 【参考方案1】:

我不明白您为什么要为此使用匹配组名称。

这是一个正则表达式,它将标记名称和标记内容匹配为编号的子匹配项。

<(tag1|tag2|tag3)>(.*?)</$1>

这是一个带有 .NET 样式组名称的变体

<(?'name'tag1|tag2|tag3)>(?'value'.*?)</\k'name'>.

编辑

RegEx 根据问题作者的说明进行了改编。

【讨论】:

托马拉克,太棒了!完美运行,正是我需要的。我试过升级你,但我必须注册。我也尝试接受答案,但没有任何反应。 无论如何都欢迎你。 ;-) 但是,如果您想报答,请您注册并接受答案。【参考方案2】:

正则表达式可能是:

/<([^>]+)>([^<]+)<\/\1>/

但这很笼统,因为我对 .NET 的转义机制了解不多。翻译它:

第一组匹配 之间的第一个标签的名称 第二组匹配内容(从>到下一个 结束检查第一个标签是否关闭

HTH

【讨论】:

请注意,由于标签内容的 [^ 当我排除打开和关闭 / 时,这个正则表达式在 VS2017 中为我工作(使用查找和替换)【参考方案3】:

感谢所有但没有一个正则表达式工作。 :( 也许我不够具体,抱歉。这是我要解析的确切 html:

...some html content <b> etc </b> ...
<user> hello <b>mitch</b> </user>
...some html content <b> etc </b> ...
<message> some html <i>message</i> <a href....>bla</a> </message>
...some html content <b> etc </b> ...

我希望现在更清楚了。我在 USER 和 MESSAGE 标签之后。

我需要两场比赛,每场比赛有两组。第一组给我标签名称(用户或消息),第二组给我标签的整个内部文本。

【讨论】:

我的回答做了一些修改,请重试! 那不是 HTML... 无论如何都不是标准 DTD。【参考方案4】:

数据是正确的 xml,还是只是看起来像?

如果是 html,那么 HTML Agility Pack 值得研究——它提供了一个 DOM(类似于 XmlDocument),您可以使用它来查询数据:

string input = @"<html>...some html content <b> etc </b> ...
<user> hello <b>mitch</b> </user>
...some html content <b> etc </b> ...
<message> some html <i>message</i> <a href....>bla</a> </message>
...some html content <b> etc </b> ...</html>";

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(input);
            foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//user | //message"))
            
                Console.WriteLine("0: 1", node.Name, node.InnerText);
                // or node.InnerHtml to keep the formatting within the content
            

这个输出:

user:  hello mitch
message:  some html message bla

如果您想要格式化标签,请使用 .InnerHtml 而不是 .InnerText。

如果是 xml,那么要使用 xml 的全谱进行编码,最好使用 xml 解析器。对于中小型 xml,将其加载到诸如 XmlDocument 之类的 DOM 中就可以了 - 然后查询节点(例如,“//*”)。对于大型 xml,XmlReader 可能是一种选择。

如果数据不必担心完整的xml,那么一些简单的正则表达式应该不会太棘手......一个简化的例子(没有属性,没有命名空间,没有嵌套的xml)可能是:

string input = @"blah <tag1> content for tag 1 </tag1> blop
<tag2> content for tag 2 </tag2> bloop
<tag3> content for tag 3 </tag3> blip";

        const string pattern = @"<(\w+)>\s*([^<>]*)\s*</(\1)>";
        Console.WriteLine(Regex.IsMatch(input, pattern));
        foreach(Match match in Regex.Matches(input, pattern)) 
            Console.WriteLine("0: 1", match.Groups[1], match.Groups[2]);
        

【讨论】:

数据不是有效的xml,而是html页面。 这看起来很有趣,我去看看,tnx。【参考方案5】:

问题是人们用来匹配标签内的东西的 ([^

这里是 Tomalak 正则表达式的一个稍微更健壮的版本,允许属性和空格:

Regex tagRegex = new Regex(@"<\s*(?<tag>" + string.Join("|", tags) + @")[^>]*>(?<content>.*?)<\s*/\s*\k<tag>\s*>", RegexOptions.IgnoreCase);

显然,如果您只需要使用一组特定的标签,您可以替换

string.Joing("|", tags)

使用硬编码管道分隔的标签列表。

正则表达式的限制是,如果您尝试匹配嵌套在另一个标签中的一个标签,它将只匹配外部标签。即

abcdefghi

它将匹配外部用户标签,但不匹配内部消息标签。

它也不处理在属性中引用的 >,如下所示:

它只会匹配

将成为标签内容的一部分。

【讨论】:

【参考方案6】:

这将为您提供所需的命名捕获组。但是,它不适用于嵌套标签。

/<(?<name>[^>]+)>(?<value>[^<]+)</\1>/

【讨论】:

以上是关于特定标签及其内容的正则表达式,按标签名称分组的主要内容,如果未能解决你的问题,请参考以下文章

用于查找 HTML 标签及其内容的正则表达式的否定 - java

美丽的汤和正则表达式

求一条c# 正则表达式,来获取HTML标签的内容

Maven-versions-plugin:用于否定不遵循特定标签格式的版本的正则表达式

xml报文标签替换正则表达式

正则表达式排除特定字符串