Ответ 1
Используйте групповой набор объекта Match, индексируя его с именем группы захвата, например.
foreach (Match m in mc){
MessageBox.Show(m.Groups["link"].Value);
}
Мне сложно найти хороший ресурс, который объясняет, как использовать Named Capturing Groups в С#. Это код, который у меня есть до сих пор:
string page = Encoding.ASCII.GetString(bytePage);
Regex qariRegex = new Regex("<td><a href=\"(?<link>.*?)\">(?<name>.*?)</a></td>");
MatchCollection mc = qariRegex.Matches(page);
CaptureCollection cc = mc[0].Captures;
MessageBox.Show(cc[0].ToString());
Однако это всегда просто показывает полную строку:
<td><a href="/path/to/file">Name of File</a></td>
Я экспериментировал с несколькими другими "методами", которые я нашел на разных сайтах, но я получаю тот же результат.
Как я могу получить доступ к именованным группам захвата, указанным в моем регулярном выражении?
Используйте групповой набор объекта Match, индексируя его с именем группы захвата, например.
foreach (Match m in mc){
MessageBox.Show(m.Groups["link"].Value);
}
Вы указываете именованную строку группы захвата, передавая ее указателю свойства Groups
результирующего объекта Match
.
Вот небольшой пример:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
String sample = "hello-world-";
Regex regex = new Regex("-(?<test>[^-]*)-");
Match match = regex.Match(sample);
if (match.Success)
{
Console.WriteLine(match.Groups["test"].Value);
}
}
}
Следующий образец кода будет соответствовать шаблону даже в случае пробелов между ними. то есть:
<td><a href='/path/to/file'>Name of File</a></td>
а также:
<td> <a href='/path/to/file' >Name of File</a> </td>
Метод возвращает true или false, в зависимости от того, соответствует ли строка ввода htmlTd шаблону или нет. Если он совпадает, параметры out содержат ссылку и имя соответственно.
/// <summary>
/// Assigns proper values to link and name, if the htmlId matches the pattern
/// </summary>
/// <returns>true if success, false otherwise</returns>
public static bool TryGetHrefDetails(string htmlTd, out string link, out string name)
{
link = null;
name = null;
string pattern = "<td>\\s*<a\\s*href\\s*=\\s*(?:\"(?<link>[^\"]*)\"|(?<link>\\S+))\\s*>(?<name>.*)\\s*</a>\\s*</td>";
if (Regex.IsMatch(htmlTd, pattern))
{
Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
link = r.Match(htmlTd).Result("${link}");
name = r.Match(htmlTd).Result("${name}");
return true;
}
else
return false;
}
Я тестировал это, и он работает правильно.
Кроме того, если у кого-то есть прецедент, где ему нужны имена групп перед выполнением поиска по объекту Regex, он может использовать:
var regex = new Regex(pattern); // initialized somewhere
// ...
var groupNames = regex.GetGroupNames();