开博第一篇:一个关于正则表达式相关的问题
今天同事提了这么一个问题
SELECT 'ZWKMZD@YY@ 123' FROM ZWKMZD@YY@ WHERE ZWKMZD@YY@.KMBH = '123'
我想替换@YY@ 为 当前年度,但是 只是替换实际表名,字符串里的不替换,
也就是替换后的结果为:SELECT 'ZWKMZD@YY@ 123' FROM ZWKMZD2010 WHERE ZWKMZD2010.KMBH = '123'
怎么弄那?
正则表达式?
其他的解决方法?
看到这个问题第一个想法就是正则表达式,首先想到的就是'.*@YY@.*',结果取出的事最外面两个单引号的内容,于是找到了lazy模式改成
'.*?@YY@.*?',这样成功的取到了要被替换的'ZWKMZD@YY@ 123' ,然后就想怎么能把@YY@其他的地方去掉,通过查资料,知道这个东西要用以前一直都没搞明白的零宽断言,也就是说,声明我要找的东西前面有 '.*?',但是前面这个东西并不是我要找的 ,同时声明我要找的东西后面有.*?',但是后面这些也不要出现在匹配结果里,这下再结合前几天看的一个关于C#Assert的文章,终于明白这个东西为什么叫作零宽断言了。记得刚学正则的时候就被这个名字弄得一楞一楞的,看很多资料也说不知道是那个人发明的词,现在看,应该是这么一回事,所谓的断言,就是说这只是一个声明,我要匹配的字符串的前面或者后面必须满足这个声明所匹配的内容,但是这个声明所匹配的内容并不是我要找的,呵呵,还是很拗口吧。零宽呢,大概就是说这个声明和我要匹配的东西之间的距离是0,不过这是我自己理解的,感觉也不是很正确,暂时先这么想把,于是加上了零宽断言之后就变成这个样子(?<='.*?)@YY@(?=.*?'),本来以为OK了,结果以运行,傻眼了,所有的@YY@全都出来了,百思不得其解,到现在还不明白为什么会这样,如果有谁知道原因希望不吝指点一下,正好这个时候同事又发过来邮件
> 不好意思,给大家说了“正则表达式”,禁锢了大家的思维范围。
>
> 正则表达式,应该是能明确知道我要描述的是怎么一样表达式,例如:以A开开头的,含有b的。 -- 这个表达式的范围是可定位的。
>
> 但是,目前,年度替换这个,可能就没有办法知道所有可能的情况,如:列名里含有单引号,等等。
>
>
>
> (此处为任命,为尊重隐私故略)提供的方式目前来看比较可行的, 从@YY@开始,看前面有多少单引号,奇数个的是不用替换的。--- 目前找到了唯一反例就是 列名、表名含有单引号的情况。
>
>
>
> 总结:很多事情的处理,可能没有办法找到最好、最终的解决方案,只能就眼前最合理、合适的。
>
这一下子就把我的思维打开了,虽然说上面提供的检查单引号的方法可取,但是一方面存在单引号转义的问题,另一方面,毕竟觉得这种方法有点低级,正则表达式的出现本来就是用来避免这种匹配的代码,所以我还是坚持认为应该从正则入手,但是呢,又不必拘泥正则,在网上查了下,发现大家一致提到处理这种配对匹配的问题一般都要用平衡组,平衡组我就不详细说了,大概意思我看懂了,但是楞是没写出来,有兴趣的朋友可以看一下这个链接来学习一下
我呢因为没看懂怎么用平衡组,所以只能硬着头皮继续琢磨,既然用第一种方法已经能把连着单引号的字符串找到,那么剩下的只要把这个字符串里面的@YY@替换掉的就行了,想到这里便豁然开朗了,以前就曾经有过一个对正则表达式的结果进行处理的例子,照着一改就行了,上次用的是委托,现在有了匿名方法,就简单多了
源码如下
private string replaceYY(string source)//传入source,就是那个SELECT 'ZWKMZD@YY@ 123' FROM ZWKMZD@YY@ WHERE ZWKMZD@YY@.KMBH = '123'
{
Regex reg = new Regex("'.*?@YY@.*?'"); //用这个正则表达式把'ZWKMZD@YY@ 123'找出来
return reg.Replace(source, delegate(Match mt)
{
return mt.Value.Replace("@YY@", "#YY#");//对找到的每有个结果,把@YY@替换成#YY#
}
).Replace("@YY@","2010").Replace("#YY#","@YY@");//没有被替换的自然就是真正要替换的了,把没被替换的@YY@替换成真正的年份,然后把刚才临时替换的#YY#在换回@YY@
}
看看注视就知道怎么回事了吧,我就不多解释了,有什么问题欢迎提问,有什么指教也欢迎赐教。偶写随笔就是把自己的一点经历保存下来,以后好回忆一下,或者做个参考资料。所以写的文笔很烂,请读者多担待了
浙公网安备 33010602011771号