从字符串中获取两个不同的匹配项

时间:2016-02-25 20:21:25

标签: c# regex

我有html锚标签,如:

<a href="http://www.stackoverflow.com"><h1><b>Stackoverflow</b></h1></a>

我写了一个正则表达式来获取href值:

href="(.+)"

然后我写了一个正则表达式来获取链接显示文本,正则表达式是:

>(\w+)<

但我无法弄清楚如何让它在一个正则表达式中工作,以便我可以一起提取href值和文本。

我如何实现这一目标?

我尝试过以下但很明显它不起作用,因为它仅匹配1组:

href="(.+)".*>|(\w+)<

4 个答案:

答案 0 :(得分:1)

如果你想使用正则表达式,这可以适用于你的例子:

href="(.*)".*>([^<]+)<

答案 1 :(得分:1)

您可以使用匹配组来捕获文本和链接:

href="(?<link>[^"]+)".*?>(?<text>\w+)<

基本思想是将正则表达式合并为一个: link-regex + SOMETEXT + text-regex

分组允许您定义正则表达式的子表达式并捕获输入字符串的子字符串。

在本文中:

<a href="http://www.stackoverflow.com"><h1><b>Stackoverflow</b></h1></a>

我们可以捕获:

href="http://www.stackoverflow.com"><h1><b>Stackoverflow<

使用这样的正则表达式:href="[^"]+".*?>\w+<

  • href="[^"]+"捕获第一部分(href="http://www.stackoverflow.com")。
  • .*?捕获中间文字(><h1><b)。
  • >\w+<捕获最后一部分(>Stackoverflow<

我们可以使用使用括号()定义的组捕获捕获的字符串的特定部分:

  • href="[^"]+" =&gt; href="([^"]+)"
  • >\w+< =&gt; >(\w+)<

此外,我们可以使用?<name>

命名群组
  • href="([^"]+)" =&gt; href="(?<link>[^"]+)"
  • >(\w+)< =&gt; >(?<text>\w+)<

最后,我们可以使用属性match.Groups

访问捕获的组
var input = "<a href=\"http://www.stackoverflow.com\"><h1><b>Stackoverflow</b></h1></a>";
var pattern = "href=\"(?<link>[^\"]+)\".*?>(?<text>\\w+)<";

var match = Regex.Match(input, pattern);

var link = match.Groups["link"].Value;
var text = match.Groups["text"].Value;

答案 2 :(得分:0)

正则表达式无法用于削减HTML或XML。这是因为它们包含嵌套结构,可能包含其他格式标记以及转义字符。

到目前为止,最好的解决方案是使用Html Agility Pack。与仅将HTML视为XML相比,Html Agility Pack可以处理未封闭的标签(如<br>)和其他奇怪的内容。

如果您仍想使用正则表达式执行此操作。然后我建议采用以下模式:

href="(.+?)"[^/]*>([^<]+)

它产生引号之间的HTML地址作为第1组,链接文本不包含第2组中的周围标记。

看起来像一只猫走过我的键盘。我想尝试剖析它并解释不同的部分。

HTML地址必须遵循href="

我们希望找到.+?的HTML地址。这意味着:一个或多个字符(.+),但尽可能少(?),否则可能吞下太多字符。我们将此表达式括在括号中,以便将其作为一个组来捕获。

然后是HTML地址后面不需要的内容:"[^/]*>"后跟零个或多个字符,/后跟>。这会将所有起始标记直到最后>,而不是结尾标记,因为它们包含/

我们快要结束了。现在,我们使用[^<]+搜索链接文本,然后再次将其捕获到一个组中。我们会搜索除<之外的所有字符,这会使搜索停在第一个结尾标记处。

答案 3 :(得分:0)

另一种方法:

string input = "<a href=\"http:////www.stackoverflow.com\"><h1><b>Stackoverflow</b></h1></a>";
string pattern = "href=\"([^\"]+)\".*>([^<]+)<";
var result = Regex.Matches(input, pattern).Cast<Match>().ToList().ConvertAll(m => new List<string>() {m.Groups[1].Value, m.Groups[2].Value});

结果是一个列表数组:

[{"http:////www.stackoverflow.com", "Stackoverflow"}]

Regex解释道:

href=\"     match href="
([^\"]+)    match all other than " (i.e. http:////www.stackoverflow.com)
\"          match "
.*>         match all until >
([^<]+)     match all other than < (i.e. Stackoverflow)
<           match <