正则表达式提供了功能强大、灵活而又高效的方法来处理文本。正则表达式的全面模式匹配表示法可以快速地分析大量的文本以找到特定的字符模式;提取、编辑、替换或删除文本子字符串;或将提取的字符串添加到集合以生成报告。对于处理字符串(例如 HTML 处理、日志文件分析和 HTTP 标头分析)的许多应用程序而言,正则表达式是不可缺少的工具。
Regex r; // 声明一个 Regex类的变量 r = new Regex("\\s2000"); // 定义表达式
3.2 Match 类表示正则表达式匹配操作的结果
以下示例使用 Regex 类的 Match 方法返回 Match 类型的对象,以便找到输入字符串中第一个匹配。此示例使用 Match 类的 Match.Success 属性来指示是否已找到匹配。
Regex r = new Regex("abc"); // 定义一个Regex对象实例 Match m = r.Match("123abc456"); // 在字符串中匹配 if (m.Success) { Console.WriteLine("Found match at position " + m.Index); //输入匹配字符的位置 }
using System; using System.Text.RegularExpressions; public class RegexTest { public static void RunTest() { Regex r = new Regex("(a(b))c"); //定义组 Match m = r.Match("abdabc"); Console.WriteLine("Number of groups found = " + m.Groups.Count); } public static void Main() { RunTest(); } }
该示例产生下面的输出:
Number of groups found = 3
3.5 CaptureCollection 类表示捕获的子字符串的序列
由于限定符,捕获组可以在单个匹配中捕获多个字符串。Captures属性(CaptureCollection 类的对象)是作为 Match 和 group 类的成员提供的,以便于对捕获的子字符串的集合的访问。例如,如果使用正则表达式 ((a(b))c)+(其中 + 限定符指定一个或多个匹配)从字符串"abcabcabc"中捕获匹配,则子字符串的每一匹配的 Group 的 CaptureCollection 将包含三个成员。
using System; using System.Text.RegularExpressions; public class RegexTest { public static void RunTest() { int counter; Match m; CaptureCollection cc; GroupCollection gc; Regex r = new Regex("(Abc)+"); //查找"Abc" m = r.Match("XYZAbcAbcAbcXYZAbcAb"); //设定要查找的字符串 gc = m.Groups; //输出查找组的数目 Console.WriteLine("Captured groups = " + gc.Count.ToString()); // Loop through each group. for (int i=0; i < gc.Count; i++) //查找每一个组 { cc = gc[i].Captures; counter = cc.Count; Console.WriteLine("Captures count = " + counter.ToString()); for (int ii = 0; ii < counter; ii++) { // Print capture and position. Console.WriteLine(cc[ii] + " Starts at character " + cc[ii].Index); //输入捕获位置 } } } public static void Main() { RunTest(); } }
此例返回下面的输出结果:
Captured groups = 2 Captures count = 1 AbcAbcAbc Starts at character 3 Captures count = 3 Abc Starts at character 3 Abc Starts at character 6 Abc Starts at character 9
3.6 Capture 类包含来自单个子表达式捕获的结果
在 Group 集合中循环,从 Group 的每一成员中提取 Capture 集合,并且将变量 posn 和 length 分别分配给找到每一字符串的初始字符串中的字符位置,以及每一字符串的长度。
Regex r; Match m; CaptureCollection cc; int posn, length; r = new Regex("(abc)*"); m = r.Match("bcabcabc"); for (int i=0; m.Groups[i].Value != ""; i++) { cc = m.Groups[i].Captures; for (int j = 0; j < cc.Count; j++) { posn = cc[j].Index; //捕获对象位置 length = cc[j].Length; //捕获对象长度 } }
该实例的核心是一个方法WriteMatches(),它把MatchCollection中的所有匹配以比较详细的方式显示出来。对于每个匹配,它都会显示该匹配在输入字符串中所在的索引,匹配的字符串和一个略长的字符串,其中包含输入文本中至多8个外围字符,其中至少有5个字符放在匹配的前面,至多5个字符放在匹配的后面(如果匹配的位置在输入文本的开头或结尾5个字符内,则结果中匹配前后的字符就会少于4个)。换言之,靠近输入文本末尾的匹配应是"and messaging ofd",匹配的前后各有5个字符,但位于输入文本的最后一个字上的匹配就应是"g of data",匹配的字后只有一个字符。因为在该字符的后面是字符串的结尾。这个长字符串可以更清楚地表明一般表达式是在什么地方查找到匹配的:
static void WriteMatches(string text, MatchCollection matches) { Console.WriteLine("Original text was: \n\n" + text + "\n"); Console.WriteLine("No. of matches: " + matches.Count); foreach (Match nextMatch in matches) { int Index = nextMatch.Index; string result = nextMatch.ToString(); int charsBefore = (Index < 5) ? Index : 5; int fromEnd = text.Length - Index - result.Length; int charsAfter = (fromEnd < 5) ? fromEnd : 5; int charsToDisplay = charsBefore + charsAfter + result.Length; Console.WriteLine("Index: {0}, \tString: {1}, \t{2}",Index, result, text.Substring(Index - charsBefore, charsToDisplay)); } }
static void Find_po() { string text = @" I can not find my position in Beijing "; string pattern = @"\bpo\S*ion\b"; MatchCollection matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture); WriteMatches(text, matches); }
这段代码还使用了名称空间RegularExpressions:
using System; using System.Text.RegularExpressions;
例如,模式"(an)+"定位序列an的任以重复。量词+只应用于它前面的一个字符,但因为我们把字符组合起来了,所以它现在把重复的an作为一个单元来对待。"(an)."应用到输入文本"bananas came to Europe late in the annals of history"上,会从bananas中选择出anan。另一方面,如果使用an+,则将从annals中选择ann,从bananas中选择出两个an。为什么(an)+选择的是anan,而没有把单个的an作为一个匹配。匹配规则是不能重复的,如果有可能重复,在默认情况下就选择较长的匹配。
String Extension(String url) { Regex r = new Regex(@"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/", RegexOptions.Compiled); return r.Match(url).Result("${proto}${port}"); }
5、小结
.NET 框架正则表达式类是基类库的一部分,并且可以和面向公共语言运行库的任何语言或工具(包括 ASP.NET 和 Visual Studio .NET)一起使用。本文给出了在C#下利用正则表达式实现字符串搜索功能的方法,通过对.NET框架下的正则表达式的研究及实例分析,总结了正则表达式的规则、选项等,方便以后朋友们的应用。