正则表达式替换重复捕获

时间:2014-07-09 12:23:03

标签: c# sql regex nhibernate log4net

我正在创建一个log4net appender,可以生成准备执行的NHibernate SQL脚本。

我想使用Regex将log4net的输出替换为可立即使用的脚本 样本输入将是

command 5:UPDATE [PlanParameter] SET Mode = @p0, DefaultValueString = @p1, ParameterID = @p2 WHERE ID = @p3;@p0 = 1 [Type: Int16 (0)], @p1 = '0' [Type: String (4000)], @p2 = 2 [Type: Int32 (0)], @p3 = 1362 [Type: Int32 (0)]

我想用

代替
UPDATE [PlanParameter] SET Mode = 1, DefaultValueString = '0', ParameterID = 2 WHERE ID = 1362

我创建了以下正则表达式:

command \d+:(?<Query>(?:(?<PreText>[\w\s\[\]]+ = )(@p\d+)(?<PostText>,?))+);(?<Parameters>(?:@p\d+ = ('?\w+'?) \[Type: \w+ \(\d+\)\],? ?)+)

完美匹配并捕捉我的样本:

Expresso matches output

我希望整个替代品由Regex引擎处理。我以为我可以使用这样的替换字符串:

${PreText}$2${PostText}

但这只会产生最后一次捕获,而不是我的最终目标。

与此同时,我使用C#来实现它:

    Regex reg = new Regex(@"command \d+:(?<Query>(?:(?<PreText>[\w\s\[\]]+ = )(@p\d+)(?<PostText>,?))+);(?<Parameters>(?:@p\d+ = ('?\w+'?) \[Type: \w+ \(\d+\)\],? ?)+)", RegexOptions.Compiled);
    string sample = @"command 5:UPDATE [PlanParameter] SET Mode = @p0, DefaultValueString = @p1, ParameterID = @p2 WHERE ID = @p3;@p0 = 1 [Type: Int16 (0)], @p1 = '0' [Type: String (4000)], @p2 = 2 [Type: Int32 (0)], @p3 = 1362 [Type: Int32 (0)]";
    Match match = reg.Match(sample);
    string result = match.Groups["Query"].Value;
    for (int i = 0; i < match.Groups[1].Captures.Count; i++)
    {
        Capture capture = match.Groups[1].Captures[i];
        result = result.Replace(capture.Value, match.Groups[2].Captures[i].Value);
    }

这完美无缺,但我确信这样做更干净利落。也许使用不同的Regex表达式?

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

这是一种更紧凑的正则表达式方法:

搜索:= (@p\d+)(?=.*?\1 (= [^\[]+))|;(?!.*= @p\d).*

替换:${2}

这会将所有参数替换为其值,并删除字符串的结尾。

请参阅regex demo底部的“替换”窗格。

<强>输出:

command 5:UPDATE [PlanParameter] SET Mode = 1 , DefaultValueString = '0' , ParameterID = 2 WHERE ID = 1362 

示例C#

String replaced = Regex.Replace(yourString, @"= (@p\d+)(?=.*?\1 (= [^\[]+))|;(?!.*= @p\d).*", "${2}");

<强>解释

  • (@p\d+)中的括号捕捉@p,数字归属于第1组
  • 前瞻(?=.*?\1 (= [^\[]+))声称接下来是......
  • .*?匹配任何字符......
  • \1第1组匹配的内容(例如@p0
  • (= [^\[]+))中的括号将文字=捕获到第2组,所有字符都不是[(我们将其用作分隔符以了解您的值结束。这是你的价值
  • OR ... |我们也会匹配字符串的结尾,并且由于匹配时没有第2组,因此替换${2}将使其无效
  • ;分号
  • 为安全起见,否定前瞻(?!.*= @p\d)声称接下来的内容不是任何字符= @p +数字
  • .*匹配分号和所有字符到字符串末尾
  • 替换字符串${2}=,第2组(值)

<强>参考