C#で名前付きキャプチャグループを使用する方法を説明する優れたリソースを見つけるのに苦労しています。これは私がこれまで持っているコードです:
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>
さまざまなWebサイトで見つけた他のいくつかの「メソッド」を試しましたが、同じ結果が得られています。
正規表現で指定された名前付きキャプチャグループにアクセスするにはどうすればよいですか?
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>
メソッドは、入力htmlTd文字列がパターンに一致するかどうかに応じて、trueまたはfalseを返します。一致する場合、出力パラメータにはそれぞれリンクと名前が含まれます。
/// <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;
}
これをテストしましたが、正常に動作します。
さらに、誰かが正規表現オブジェクトで検索を実行する前にグループ名が必要なユースケースがある場合、次のように使用できます。
var regex = new Regex(pattern); // initialized somewhere
// ...
var groupNames = regex.GetGroupNames();