myRegex.GetGroupNames()
Seems to r开发者_JAVA技巧eturn the numbered groups as well... how do I get only the named ones?
A solution using the actual Match object would be fine as well.
Does using the RegexOptions.ExplicitCapture
option when creating the regex do what you want ? e.g.
Regex theRegex = new Regex(@"\b(?<word>\w+)\b", RegexOptions.ExplicitCapture);
From MSDN:
Specifies that the only valid captures are explicitly named or numbered groups of the form
(?<name>...)
. This allows unnamed parentheses to act as noncapturing groups without the syntactic clumsiness of the expression(?:...)
.
So you won't need to worry about whether users of your API may or may not use non-capturing groups if this option is set.
See the other comments/answers about using (?:)
and/or sticking with "one style". Here is my best approach that tries to directly solve the question:
var named = regex.GetGroupNames().Where(x => !Regex.IsMatch(x, "^\\d+$"));
However, this will fail for regular expressions like (?<42>...)
.
Happy coding.
public string[] GetGroupNames(Regex re)
{
var groupNames = re.GetGroupNames();
var groupNumbers = re.GetGroupNumbers();
Contract.Assert(groupNames.Length == groupNumbers.Length);
return Enumerable.Range(0, groupNames.Length)
.Where(i => groupNames[i] != groupNumbers[i].ToString())
.Select(i => groupNames[i])
.ToArray();
}
Actually, this will still fail when the group name and number happen to be the same :\ But it will succeed even when the group name is a number, as long as the number is not the same as its index.
精彩评论