Что-то вроде следующего?
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));
}
выход
foo: no match
dog: two-2 = dog
bar: no match
fish: four-4 = fish
Сначала мы создаем экземпляр Regex
, избегая имен групп и комбинируя их с шаблонами. Любой несловесный символ заменяется последовательностью _nnn_
, где nnn является его значением UTF-32.
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) + "_";
}
Для совпадений библиотека .NET не дает нам простого способа получить имя группы, поэтому мы должны пойти другим путем: для каждого имени группы мы проверяем, совпадает ли эта группа и, если это так, удаляют ее имя и сообщите вызывающей стороне как имя, так и захваченную подстроку.
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));
}