如何在 C # 正则表达式中获取被捕获的组的名称?

有没有办法在 C # 中获取被捕获的组的名称?

string line = "No.123456789  04/09/2009  999";
Regex regex = new Regex(@"(?<number>[\d]{9})  (?<date>[\d]{2}/[\d]{2}/[\d]{4})  (?<code>.*)");


GroupCollection groups = regex.Match(line).Groups;


foreach (Group group in groups)
{
Console.WriteLine("Group: {0}, Value: {1}", ???, group.Value);
}

我想得到这个结果:

Group: [I don´t know what should go here], Value: 123456789  04/09/2009  999
Group: number, Value: 123456789
Group: date,   Value: 04/09/2009
Group: code,   Value: 999
71230 次浏览

Use GetGroupNames to get the list of groups in an expression and then iterate over those, using the names as keys into the groups collection.

For example,

GroupCollection groups = regex.Match(line).Groups;


foreach (string groupName in regex.GetGroupNames())
{
Console.WriteLine(
"Group: {0}, Value: {1}",
groupName,
groups[groupName].Value);
}

You should use GetGroupNames(); and the code will look something like this:

    string line = "No.123456789  04/09/2009  999";
Regex regex =
new Regex(@"(?<number>[\d]{9})  (?<date>[\d]{2}/[\d]{2}/[\d]{4})  (?<code>.*)");


GroupCollection groups = regex.Match(line).Groups;


var grpNames = regex.GetGroupNames();


foreach (var grpName in grpNames)
{
Console.WriteLine("Group: {0}, Value: {1}", grpName, groups[grpName].Value);
}

The cleanest way to do this is by using this extension method:

public static class MyExtensionMethods
{
public static Dictionary<string, string> MatchNamedCaptures(this Regex regex, string input)
{
var namedCaptureDictionary = new Dictionary<string, string>();
GroupCollection groups = regex.Match(input).Groups;
string [] groupNames = regex.GetGroupNames();
foreach (string groupName in groupNames)
if (groups[groupName].Captures.Count > 0)
namedCaptureDictionary.Add(groupName,groups[groupName].Value);
return namedCaptureDictionary;
}
}


Once this extension method is in place, you can get names and values like this:

    var regex = new Regex(@"(?<year>[\d]+)\|(?<month>[\d]+)\|(?<day>[\d]+)");
var namedCaptures = regex.MatchNamedCaptures(wikiDate);


string s = "";
foreach (var item in namedCaptures)
{
s += item.Key + ": " + item.Value + "\r\n";
}


s += namedCaptures["year"];
s += namedCaptures["month"];
s += namedCaptures["day"];

The Regex class is the key to this!

foreach(Group group in match.Groups)
{
Console.WriteLine("Group: {0}, Value: {1}", regex.GroupNameFromNumber(group.Index), group.Value);
}

http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.groupnamefromnumber.aspx

Since .NET 4.7, there is Group.Name property available.

To update the existing extension method answer by @whitneyland with one that can handle multiple matches:

public static List<Dictionary<string, string>> MatchNamedCaptures(this Regex regex, string input)
{
var namedCaptureList = new List<Dictionary<string, string>>();
var match = regex.Match(input);


do
{
Dictionary<string, string> namedCaptureDictionary = new Dictionary<string, string>();
GroupCollection groups = match.Groups;


string[] groupNames = regex.GetGroupNames();
foreach (string groupName in groupNames)
{
if (groups[groupName].Captures.Count > 0)
namedCaptureDictionary.Add(groupName, groups[groupName].Value);
}


namedCaptureList.Add(namedCaptureDictionary);
match = match.NextMatch();
}
while (match!=null && match.Success);


return namedCaptureList;
}

Usage:

  Regex pickoutInfo = new Regex(@"(?<key>[^=;,]+)=(?<val>[^;,]+(,\d+)?)", RegexOptions.ExplicitCapture);


var matches = pickoutInfo.MatchNamedCaptures(_context.Database.GetConnectionString());


string server = matches.Single( a => a["key"]=="Server")["val"];