正则表达式是一种强大的文本处理工具,它允许通过定义一个模式来验证、提取、编辑、替换或删除文本中的部分内容。尽管正则表达式功能强大,但其语法复杂,对于不常使用的人来说,记忆和编写正则表达式是一项挑战。本文介绍一种.NET语言中的扩展方法,旨在简化正则表达式的使用,使得即使是不熟悉正则表达式语法的用户也能轻松处理字符串。
正则表达式引擎需要文本分析、一个正则表达式引擎和一个正则表达式模式。不同的正则表达式引擎有不同的语法规则。在.NET中,正则表达式引擎由System.Text.RegularExpressions.Regex类提供支持。虽然有许多优秀的教程介绍正则表达式语法,但正则表达式的缺点在于其语法对于人类来说并不友好。
正则表达式的语法虽然对引擎友好,但对人类并不友好。不熟悉语法的人可能需要花费大量时间编写有效的表达式,并进行测试以确保其准确性。此外,确保正则表达式不仅匹配预期的内容,而且只匹配预期的内容,是另一项挑战。
受到SQL中LIKE操作符的启发,提出了一种简化的正则表达式语法,以减少操作符的数量。例如,使用问号(?)表示任意字符,百分号(%)表示零个或多个字符,星号(*)表示零个或多个非空白字符(基本上是一个单词),井号(#)表示任意单个数字(0-9)。
正则表达式引擎通常用于以下操作:确定文本是否匹配给定模式(Like)、在文本中查找给定模式的出现(Search)以及从文本中提取与给定模式匹配的字符串(Extract)。本文介绍的扩展方法实现了这些操作,提供了一种替代正则表达式引擎的简单方法。
Like扩展方法简单地返回输入字符串是否匹配给定模式。以下示例展示了如何使用Like方法:
var result0 = "TA0E02391-A0DF-4772-B39A-C11F7D63C495".Like("????????-????-????-????-????????????");
var result1 = "This is a guid TA0E02391-A0DF-4772-B39A-C11F7D63C495".Like("%????????-????-????-????-????????????");
var result2 = "TA0E02391-A0DF-4772-B39A-C11F7D63C495 is a guid".Like("????????-????-????-????????????%");
var result3 = "this string TA0E02391-A0DF-4772-B39A-C11F7D63C495 contains a guid".Like("%????????-????-????-????-????????????%");
var result4 = "TA0E02391-A0DF-4772-B39A-C11F7D63C495".Like("%????????-????-????-????-????????????");
以上示例均返回true,表示输入字符串符合其模式。
Search扩展方法检索给定文本中第一个匹配给定模式的实例。以下示例展示了如何使用Search方法:
var result5 = "this string [TA0E02391-A0DF-4772-B39A-C11F7D63C495] contains a string matching".Search("[????????-????-????-????-????????????]");
Console.WriteLine(result5); // 输出: [TA0E02391-A0DF-4772-B39A-C11F7D63C495]
Extract方法类似于Search,但它返回与模式组匹配的字符串数组,而不是匹配整个模式的字符串。以下示例展示了如何使用Extract方法:
var result6 = "this string [TA0E02391-A0DF-4772-B39A-C11F7D63C495] contains a string matching".Extract("[????????-????-????-????-????????????]");
// 结果是一个数组,包含模式的每个部分:{"TA0E02391", "A0DF", "4772", "B39A", "C11F7D63C495"}
var result7 = "this string contains an email: toto@domain.com".Extract("*?@?*.?*");
// 结果是一个数组,包含模式的每个部分:{"toto", "domain", "com"}
public static class StringExt
{
public static bool Like(this string item, string searchPattern)
{
var regex = GetRegex("^" + searchPattern);
return regex.IsMatch(item);
}
public static string Search(this string item, string searchPattern)
{
var match = GetRegex(searchPattern).Match(item);
if (match.Success)
{
return item.Substring(match.Index, match.Length);
}
return null;
}
public static List Extract(this string item, string searchPattern)
{
var result = item.Search(searchPattern);
if (!string.IsNullOrWhiteSpace(result))
{
var splitted = searchPattern.Split(new[] { '?', '%', '*', '#' }, StringSplitOptions.RemoveEmptyEntries);
var temp = result;
var final = new List();
foreach (var x in splitted)
{
var pos = temp.IndexOf(x);
if (pos > 0)
{
final.Add(temp.Substring(0, pos));
temp = temp.Substring(pos);
}
temp = temp.Substring(x.Length);
}
if (temp.Length > 0) final.Add(temp);
return final;
}
return null;
}
private static Regex GetRegex(string searchPattern)
{
return new Regex(searchPattern
.Replace("\\", "\\\\")
.Replace(".", "\\.")
.Replace("{", "\\{")
.Replace("}", "\\}")
.Replace("[", "\\[")
.Replace("]", "\\]")
.Replace("+", "\\+")
.Replace("$", "\\$")
.Replace(" ", "\\s")
.Replace("#", "[0-9]")
.Replace("?", ".")
.Replace("*", "\\w*")
.Replace("%", ".*"), RegexOptions.IgnoreCase);
}
}