良方治奇病,Visual Studio正则替换大法 (转)

 在工作中,尤其是重构的时候,对原有大批量的代码进行修改是一件很累人的工作,稍有不甚,可能就会有遗漏。本文今天就与大家一起探索Visual Studio中非常实用但却鲜为人知的功能,Regex Replace(正则替换)。      
      
某天,我遇到一堆这样的代码:

      大家都看出来了,发现两个问题:

            1.       检查是否为空的部分不是太合理;
            2.       DataReader使用索引的方式很难维护,要是查询增加字段,那就只能在后面增加了。

      
团队中有人重写了DataReader的方法,改进了这两点,就是使用rdr.GetInt32(“ID”)这种使用字段名的访问方式访问数据,另外还有一个重载,rdr.GetInt32(“ImageNumber”,0)这种为Null情况下赋默认值的操作,现在我们就要开始对代码就行重构。
      发现一个问题,直接用Find & Replace肯定不行,因为里面即有相同点,又有不同点,最主要的不同就是每一行的Index参数都不同。

      于是开始在ReplaceFind Options里面找线索,发现最下方有一个Use,选中后可以选Regular ExpressionsWildcardsWildcards其实是类似于系统的文件搜索方式,用“*”匹配任意文本,由于不在本文今天的讨论范围之内,就不赘述了。

         
      正则表达式相信大家都很熟悉了,但这里的正则和以往大家所熟悉的正则有点不同,语法上有点不同,他是专门用于Visual Studio的,详细情往下看。

 
      我们先开始搜索吧,先采集一段样本,直接复制ID = rdr.GetValue(0) == DBNull.Value ? 0 : rdr.GetInt32(0)Find What输入框中,点击Find Next,发现提示“:”未知。

      大家都想到了,正则中,很多符号都有自己定义的意思的,而我们这里不用他在正则中的意思,而是要搜索这个符号,所以我们要在有些符号前加上转义符“\”,变成ID = rdr\.GetValue\(0\) == DBNull.Value ? 0 \: rdr\.GetInt32\(0\)”,话说有人就要问了,“=”“?”怎么就不用呢?难道没有意思么?我的回答是:请参考http://msdn.microsoft.com/en-us/library/2k3te2cs.aspx  

      其实也不用那么麻烦,直接点输入框右边的三角,就可以得到常用的符号列表:

      现在点击Find Next,发现已经能找到第一条符合的了,现在我们要抽取公共的部分,改写变化的部分,我们发现其实就是第一个部分的属性名和两个Index参数以及一个默认值三部分是变化的,我们将Find What改写为::i = rdr\.GetValue\(:z\) == DBNull.Value ? :z \: rdr\.GetInt32\(:z\)”,其中,:i表示Identifier:z表示Integer

      现在我们再点击Find Next发现找到了,再点一下,发现问题了,还是这句,只是开头的变量名被高亮的部分少了一个字符,发现问题就要解决啊!我们为:i加上单词边界符”<“”>”,整句就变成<:i> = rdr\.GetValue\(:z\) == DBNull.Value ? :z \: rdr\.GetInt32\(:z\)”,再点Find Next。发现终于成功了。

      以上是查找部分,你会了么?接下来就要进行我们激动人心的替换了!
      我总结了一句话:"{}"包围起不变的变化,用"\index"恢复她
      
      解释一下,什么叫不变的变化呢?就如以上所示的
“<:i>”,他是一个变量,每一行的都不同,所以他是变化的,而替换后的结果要求这些变化要保留,就是变量名替换后还是原来的。
      
比如:       ID=xxxx;
                        
Name=xxxx;
      替换后要为:ID=yyyy;
                        
Name=yyyy;
      
      好!现在开始实施这句话,将
”<:i>”变为”<{:i}>“。因为索引值是要抛弃的,而默认值是要保留的,所以整句话就变成 <{:i}> = rdr\.GetValue\(:z\) == DBNull.Value ? {:z} \: rdr\.GetInt32\(:z\)
      
Replace With当中,我们写上要替换成的语句!注意:在Replace With中,因为不需要进行正则查找,所以符号可以直接输,不用“\”转义,但”\”别有他用,用”\index”表示搜索式中被标记的第index个内容,index1开始,"\0“表示搜索到的原内容。所以我们的Replace With\1 =rdr.GetInt32("\1",\2) 开始替换。
      
      
替换前:








替换后:

 
      大家可能发现了,只替换了一部分GetInt32的,还有一堆GetString的,这里就留给大家去研究了!

 

我总结一下今天我们搜索条件的变化,给大家一个明显的思路提示。

1.       取样:ID = rdr.GetValue(0) == DBNull.Value ? 0 : rdr.GetInt32(0)

2.       转义:ID = rdr\.GetValue\(0\) == DBNull.Value ? 0 \: rdr\.GetInt32\(0\)

3.       抽象::i = rdr\.GetValue\(:z\) == DBNull.Value ? :z \: rdr\.GetInt32\(:z\)

4.       缩范:<:i> = rdr\.GetValue\(:z\) == DBNull.Value ? :z \: rdr\.GetInt32\(:z\)

5.       标记:<{:i}> = rdr\.GetValue\(:z\) == DBNull.Value ? {:z} \: rdr\.GetInt32\(:z\)

6.       替换:\1 =rdr.GetInt32("\1",\2)

 
      怎么样?这个正则不太繁吧!

posted @ 2009-08-04 11:15  awp110  阅读(176)  评论(0编辑  收藏  举报