使用正则表达式实现像SQL中LIKE语句中的%和_通配

在项目中我们经常遇到将数据库的数据取到后再次进行筛选过滤的情况。LINQ to Entity提供了统一的查询接口并且可以高效的完成工作,但是对于我们常在SQL中使用的%和_这样的通配符并没有支持。我们只能通过String.Contains方法来实现简单的通配。使用String.Contains方法是无法达到在查询串中使用通配符的目的的。正则表达式虽然晦涩难懂,但功能十分强大,解决个统配符绰绰有余。

创新互联专注为客户提供全方位的互联网综合服务,包含不限于成都网站建设、网站设计、宁县网络推广、小程序开发、宁县网络营销、宁县企业策划、宁县品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联为所有大学生创业者提供宁县建站搭建服务,24小时服务热线:18980820575,官方网址:www.cdcxhl.com

代码如下:

    public static class LINQHelper
    {
        /// 
        /// The all regex meta chars
        /// 
        private static string[] REGEX_META_CHARS = { "\\", ".", "^", "$", "*", "+", "?", "{", "}", "(", ")", "[", "]" };

        /// 
        /// Like method work as SQL like
        /// 
        /// The search string
        /// The SQL pattern
        /// Whether match or not
        public static bool Like(this string searchString, string sqlPattern)
        {
            if (searchString == null)
            {
                return false;
            }
            else
            {
                string convertedPattern = EscapeRegexMetaChars(sqlPattern).Replace("_", ".").Replace("%", ".*");
                convertedPattern = String.Format("^{0}$", convertedPattern);

                return Regex.IsMatch(searchString, convertedPattern, RegexOptions.Singleline);
            }
        }

        /// 
        /// Like method work as SQL like
        /// 
        /// The search string
        /// The SQL pattern
        /// The escape char
        /// Whether match or not
        public static bool Like(this string searchString, string sqlPattern, char escapeChar)
        {
            if (searchString == null)
            {
                return false;
            }
            else
            {
                string convertedPattern = EscapeRegexMetaChars(sqlPattern);
                convertedPattern = ReplaceWildcards(convertedPattern, '_', ".", escapeChar);
                convertedPattern = ReplaceWildcards(convertedPattern, '%', ".*", escapeChar);
                convertedPattern = String.Format("^{0}$", convertedPattern);

                return Regex.IsMatch(searchString, convertedPattern, RegexOptions.Singleline);
            }
        }

        /// 
        /// Replace wildcards
        /// 
        /// The replacement string
        /// The wildcard
        /// The replace wild char to
        /// The escape char
        /// The converted search value
        private static string ReplaceWildcards(string replacement, char wildcard, string replaceTo, char escapeChar)
        {
            string regexExpression = String.Format("(^|[^{0}])({1}+)", escapeChar, wildcard);
            return Regex.Replace(replacement, regexExpression, match => String.Format("{0}{1}", match.Groups[1].Value, match.Groups[2].Value.Replace(wildcard.ToString(), replaceTo)))
                .Replace(string.Format("{0}{1}", escapeChar, wildcard), wildcard.ToString());
        }

        /// 
        /// Escape regex meta chars
        /// 
        /// The replacement string
        /// The converted search value
        private static string EscapeRegexMetaChars(string replacement)
        {
            string resultString = replacement;
            foreach (string metaChar in REGEX_META_CHARS)
            {
                resultString = resultString.Replace(metaChar, string.Format(@"\{0}", metaChar));
            }

            return resultString;
        }
    }

 

首先,要将查询串中所有正则表达式的元字符转义为普通字符,这样才能安全的使用正则表达式进行匹配。

然后,将”_”和”%”替换成相应的正则表达式,即”_”替换成”.”,”%”替换成”.*”。这里还考虑到SQL的LIKE语句也有转义符功能,即如果使用ESCAPE子句则LIKE串中转义符后的”_”和”%”变为普通字符而不是通配符。所以当使用转义符时处理如下:

  • 将所有不以转义符引导的通配符替换。

  • 再将转义符引导的通配符的转义符去掉,即将通配符转义为普通字符。

以下是几个转换的例子:

  • LIKE ‘A_B’ 转换为 A.B

  • LIKE ‘A%B’ 转换为 A.*B

  • LIKE ‘A~_B’ ESCAPE ‘~’ 转换为 A_B

  • LIKE ‘A.B’ 转换为 A/.B

优点:我们可以在LINQ语句的条件中方便的使用Like方法去过滤数据,LINQ语句整体上会保持很好的可读性。

缺点:Like 方法会被调用n次(n取决于数据量),解析SQL pattern到正则表达式pattern的代码就要被重复执行n次。因此当数据量过大时解析pattern会消耗一定的资源。当然这可以通过一些方法去解决,如缓存解析结果,或改为传入就是解析好的正则表达式等。


新闻标题:使用正则表达式实现像SQL中LIKE语句中的%和_通配
路径分享:http://pwwzsj.com/article/jdophg.html