我有一个正则表达式,如下:
(?<one-1>cat)|(?<two-2>dog)|(?<three-3>mouse)|(?<four-4>fish)
当我尝试在.Net应用程序中使用此模式时,它失败了,因为组名称中包含“ – ”.
所以,作为一种解决方法,我尝试使用两个正则表达式,第一个:
(?<A>cat)|(?<Be>dog)|(?<C>mouse)|(?<D>fish)
将我正在寻找的原始案例与我可以控制的组名相匹配.
然后,我打算使用正则表达式中的正则表达式组名,如下所示:
(?<A>one-1)|(?<Be>two-2)|(?<C>three-3)|(?<D>four-4)
我会这样做,通过找到匹配此模式的字符串并确定组名是否相等.
我知道这看起来有点令人费解.感谢您提供的任何帮助.
解决方法
以下是什么?
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)); }