良方治奇病,Visual Studio正则替换大法 (转)
某天,我遇到一堆这样的代码:
大家都看出来了,发现两个问题:
1. 检查是否为空的部分不是太合理;
2. DataReader使用索引的方式很难维护,要是查询增加字段,那就只能在后面增加了。
团队中有人重写了DataReader的方法,改进了这两点,就是使用rdr.GetInt32(“ID”)这种使用字段名的访问方式访问数据,另外还有一个重载,rdr.GetInt32(“ImageNumber”,0)这种为Null情况下赋默认值的操作,现在我们就要开始对代码就行重构。
发现一个问题,直接用Find & Replace肯定不行,因为里面即有相同点,又有不同点,最主要的不同就是每一行的Index参数都不同。
于是开始在Replace的Find Options里面找线索,发现最下方有一个Use,选中后可以选Regular Expressions和Wildcards。Wildcards其实是类似于系统的文件搜索方式,用“*”匹配任意文本,由于不在本文今天的讨论范围之内,就不赘述了。
正则表达式相信大家都很熟悉了,但这里的正则和以往大家所熟悉的正则有点不同,语法上有点不同,他是专门用于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个内容,index从1开始,"\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)
怎么样?这个正则不太繁吧!