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

本文关键字:两个 获取 一个 字符串 | 更新日期: 2023-09-27 18:36:17

我有html锚标签,例如:

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

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

href="(.+)"

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

>('w+)<

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

我怎样才能做到这一点?

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

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

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

如果你想

使用正则表达式,这可以适用于你的示例:

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

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

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="[^"]+" => href="([^"]+)"
  • >'w+< => >('w+)<

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

  • href="([^"]+)" => href="(?<link>[^"]+)"
  • >('w+)< => >(?<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;

另一种方法:

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"}]

正则表达式解释:

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 <

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

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


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

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

它生成组 1 中的引号和组 2 中没有周围标记的链接文本之间的 HTML 地址。

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

HTML 地址必须跟在 href=" 后面。

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

然后是HTML地址后面不需要的东西:"[^/]*>,一个"后跟零个或多个字符,除了/后跟>。这会吞下所有起始标签直到最后一>,但不会吞下结束标签,因为这些标签包含/

我们快要走到尽头了。现在我们使用[^<]+搜索链接文本,并再次在组中捕获它。我们搜索除 < 之外的所有字符,这使得搜索在第一个结束标记处停止。