Something in 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)); }
Exit
foo: no match
dog: two-2 = dog
bar: no match
fish: four-4 = fish
First, we create an instance of Regex by escaping group names and combining them with templates. 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 coincidences, the .NET library does not give us an easy way to get the name of a group, so we need to go a different way: for each group name we check if this group matches and if its unescape its name and let the caller know both the name and the 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)); }