搜索并替换C#表达式

时间:2015-06-12 07:29:38

标签: c# regex visual-studio roslyn

我一次又一次地发现自己需要改变一个方法调用与另一个方法调用的使用。

E.g。我有100次类似于此的方法调用:

Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray());

需要更改为

Helper.GetIntFromData(packetData, offset, length);

使用正则表达式可以相对容易地解决这个问题。但是,如果空白(有时)发挥作用呢?

Helper.GetIntFromData(packetData
    .Skip(  offset  )
    .Take(  length  )
    .ToArray()  
);

仍然可以使用正则表达式,但它现在是一个无法读取的可选空格标记。

好的,但是如果参数并不总是简单的标识符,而是任意表达式怎么办?

Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) )
    .Take( length1 / length2 ).ToArray());

这是正则表达式真正崩溃的地方。

我的问题是:

今天可以这样做吗? (以某种方式让你保持理智,即没有正则表达式)

是否有VS扩展或独立工具可以处理更高(语义)级别的C#代码?

允许我搜索的东西(我想象):

Helper.GetIntFromData($expr1.Skip($expr2).Take($expr3).ToArray())

并替换为

Helper.GetIntFromData($1, $2, $3)

C#是否存在这样的工具? (我想它可以围绕罗斯林建造。)

3 个答案:

答案 0 :(得分:1)

在再想一想之后,你想要达到的目标是危险的,最好避免。 RegEx匹配/替换是一项有限的功能。它无法“理解”复杂的代码,并且必然会失败。考虑一个例子(如果代码甚至有意义的话,让我们忽略一下):

Helper.GetIntFromData(packetData.Skip(skipArray.Take(1)).Take(length).ToArray());

没有专门为避免“错误Take”而定制的正则表达式没有机会。您的自动替换方法会破坏您的代码,这是一个时间问题,您唯一的希望是它足以产生编译时错误。它可能同样难以找到运行时异常或更糟糕的,无法解释的行为。代码重构应该使用了解代码的工具,而不是识别文本模式的工具。

答案 1 :(得分:1)

Resharper具有语义搜索和替换

 $user_coutry_id = 1;
 $ship_cost ="";
 foreach ($arr as $key =>  $value) {
    if($arr[$key]["country_id"]==$user_coutry_id){
         $ship_cost = $arr[$key]["ship_cost"];
    }
 } 
 echo $ship_cost;
// return 1 as you expect. 

Helper.GetIntFromData(packetData.Skip($offset$).Take($length$).ToArray());

它对白色空间不敏感,您可以将令牌匹配限制为某些类型。我一直用它来做你想做的事。我还没有看到任何基于roslyn的项目,所有用户都这么做。

以下是resharpers网站上的功能介绍

http://blog.jetbrains.com/dotnet/2010/04/07/introducing-resharper-50-structural-search-and-replace/

答案 2 :(得分:0)

如果可能的话,我会手动使用#34;但是使用简单的正则表达式(是的,我知道你说没有它们,而且Amit的回答是"看起来对,"虽然我没有检查边缘情况)。

这样的事情:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.io.StdIn


object Y extends App {
   TimerFuture(Future{Thread.sleep(200); "Hello"})
     .onSuccess({case ResultWithTime(r, t) => println(s"Took $t ms to get: $r")})
   TimerFuture(Future{Thread.sleep(100); throw new NullPointerException()})
     .onFailure({case f: FailureWithTime => println(s"Took ${f.time} ms to get: ${f.getCause}")})
   StdIn.readLine()
}

Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray()); Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) ) .Take( length1 / length2 ).ToArray()); 替换为(Helper.GetIntFromData.*?)\.Skip\(以获取

\1,

然后将Helper.GetIntFromData(packetData, offset).Take(length).ToArray()); Helper.GetIntFromData(obj.GetData(true), 7 + GetOffset( item.GetData() ) ) .Take( length1 / length2 ).ToArray()); 替换为(Helper.GetIntFromData.*?)\)\.Take\(以获取

\1,

最后用Helper.GetIntFromData(packetData, offset, length).ToArray()); Helper.GetIntFromData(obj.GetData(true), 7 + GetOffset( item.GetData() ) , length1 / length2 ).ToArray()); 替换(Helper.GetIntFromData.*?)\)\.ToArray\(\)\);以获取

\1\);