Regex,用于指定标记及其内容,按标记名称分组
本文关键字:用于 Regex | 更新日期: 2023-09-27 17:47: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"
有什么想法吗?
我不明白为什么要使用匹配组名称。
下面是一个正则表达式,它将标记名称和标记内容匹配为编号的子匹配。
<(tag1|tag2|tag3)>(.*?)</$1>
这是一个带有的变体。NET样式组名称
<(?'name'tag1|tag2|tag3)>(?'value'.*?)</'k'name'>.
编辑
RegEx根据问题作者的澄清进行了调整。
Regex可能是:
/<([^>]+)>([^<]+)<'/'1>/
但这是一般性的,因为我对逃避的男子主义了解不多。NET。翻译:
- 第一组在<和>
- 第二组匹配内容(从>到下一<
- 结束检查第一个标签是否关闭
HTH
感谢所有正则表达式,但没有一个有效。:(也许我不够具体,很抱歉。以下是我试图解析的确切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标签。
我需要两场比赛,每场有两组。第一组wp会给我标签名称(用户或消息),第二组wp则会给我整个标签内部文本。
数据是正确的xml,还是看起来像它?
如果它是html,那么html敏捷包值得研究——它提供了一个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,将其加载到DOM(如XmlDocument)中就可以了,然后查询节点(例如,"//*")。对于巨大的xml,XmlReader可能是一个选项。
如果数据不必担心完整的xml,那么一些简单的regex应该不会太棘手。。。一个简化的例子(没有属性,没有名称空间,没有嵌套的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]);
}
问题是,人们用来匹配标签内内容的([^<]*)与开头<嵌套标记的结束标记与外部标记不匹配,因此regex失败。
下面是Tomalak正则表达式的一个稍微健壮一点的版本,允许使用属性和空白:
Regex tagRegex = new Regex(@"<'s*(?<tag>" + string.Join("|", tags) + @")[^>]*>(?<content>.*?)<'s*/'s*'k<tag>'s*>", RegexOptions.IgnoreCase);
显然,如果你只需要使用一组特定的标签,你可以更换
string.Joing("|", tags)
带有硬编码管道分离标签列表。
正则表达式的局限性在于,如果您有一个试图匹配的标签嵌套在另一个标签中,它将只匹配外部标签。即
<user>abc<消息>def<message>ghi<用户>
它将匹配外部用户标记,但不匹配内部消息标记。
它也不处理属性中引用的>:
<user attrib="oops>">
它将刚好匹配
<user attrib="oops>
作为标签和
">
将是标签内容的一部分。
这将为您提供所需的命名捕获组。但是,它不适用于嵌套标记。
/<(?<name>[^>]+)>(?<value>[^<]+)</'1>/