Something along the lines of the following?
string[,] patterns = {
{ "one-1", "cat" },
{ "two-2", "dog" },
{ "three-3", "mouse" },
{ "four-4", "fish" },
};
var regex = buildRegex(patterns);
string[] tests = { "foo", "dog", "bar", "fish" };
foreach (var t in tests) {
var m = regex.Match(t);
Console.WriteLine("{0}: {1}", t, reportMatch(regex, m));
}
Output
foo: no match
dog: two-2 = dog
bar: no match
fish: four-4 = fish
First we build up a Regex
instance by escaping the group names and combining them with the patterns. Any non-word character is replaced with the sequence _nnn_
where nnn is its UTF-32 value.
private static Regex buildRegex(string[,] inputs)
{
string regex = "";
for (int i = 0; i <= inputs.GetUpperBound(0); i++) {
var part = String.Format(
"(?<{0}>{1})",
Regex.Replace(inputs[i,0], @"([\W_])", new MatchEvaluator(escape)),
inputs[i,1]);
regex += (regex.Length != 0 ? "|" : "") + part;
}
return new Regex(regex);
}
private static string escape(Match m)
{
return "_" + Char.ConvertToUtf32(m.Groups[1].Value, 0) + "_";
}
For matches, the .NET library doesn't give us an easy way to get a group's name, so we have to go the other way: for each group name, we check whether that group matched and if so unescape its name and let the caller know both name and captured substring.
private static string reportMatch(Regex regex, Match m)
{
if (!m.Success)
return "no match";
foreach (var name in regex.GetGroupNames()) {
if (name != "0" && m.Groups[name].Value.Length > 0)
return String.Format(
"{0} = {1}",
Regex.Replace(name, @"_(\d+)_",
new MatchEvaluator(unescape)),
m.Groups[name].Value);
}
return null;
}
private static string unescape(Match m)
{
return Char.ConvertFromUtf32(int.Parse(m.Groups[1].Value));
}