string filepath = @"\folder\aaa.bb"; string pat = @"^.*\\(?:.+)\\(.+)\.(.+)$"; var m = Regex.Match(filepath, pat); if (m.Success) { Console.WriteLine("{0}", m.Groups[1].Value); // aaa Console.WriteLine("{0}", m.Groups[2].Value); // bb } else Console.WriteLine("No match"); Console.ReadLine();(4) The Groups[] collection can be indexed by
string filepath = @"\folder\aaa.bb"; string pat = @"^.*\\(?:.+)\\(?<FileStem>.+)\.(?<FileExtension>.+)$"; var m = Regex.Match(filepath, pat); if (m.Success) { Console.WriteLine("{0}", m.Groups["FileStem"].Value); // aaa Console.WriteLine("{0}", m.Groups["FileExtension"].Value); // bb } else Console.WriteLine("No match"); Console.ReadLine();(5) You can even nest named groups
string filepath = @"\folder\aaa.bb"; string pat = @"^.*\\(?:.+)\\(?<FileName>(?<FileStem>.+)\.(?<FileExtension>.+))$"; var m = Regex.Match(filepath, pat); if (m.Success) { Console.WriteLine("{0}", m.Groups["FileStem"].Value); // aaa Console.WriteLine("{0}", m.Groups["FileExtension"].Value); // bb Console.WriteLine("{0}", m.Groups["FileName"].Value); // aaa.bb } else Console.WriteLine("No match"); Console.ReadLine();(6) Let me also introduce zero-width assertions. They can be positive/negative and lookahead/lookbehind
string[] test = { "1", //false "2a", // false "H1a4t", // false "helloThere", // false "hello1there", // false "hello1There" // true }; // (?=.*\d.*) zero-width positve lookeahead. assure at least one digit // (?=.*[a-z].*) zero-width positve lookeahead. assure at least one lower case char // (?=.*[A-Z].*) zero-width positve lookeahead. assure at least one upper case char // .{6,} need at least six chars string pat = @"^((?=.*\d.*)(?=.*[a-z].*)(?=.*[A-Z].*).{6,})$"; foreach( var s in test ) { var m = Regex.Match(s, pat); Console.WriteLine("{0}: {1}", m.Success, s); } Console.ReadLine();(7) Finally, if you want to discover more fun and goodies - there are plenty