C# 正则表达式替换重复捕获

C# 正则表达式替换重复捕获,c#,sql,regex,nhibernate,log4net,C#,Sql,Regex,Nhibernate,Log4net,我正在创建一个log4netappender,它生成准备执行的NHibernateSQL脚本 我想使用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 (400

我正在创建一个
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+\)\],? ?)+)
但这只会带来最后一次捕获,而不是我的最终目标

与此同时,我用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 reg=newregex(@“command\d+:(?:(?[\w\s\[\]+=)(@p\d+(?)+)+);(?(?:@p\d+=('?\w+')\[类型:\w+\(\d+\]),?)+”,RegexOptions.Compiled);
字符串样本=@“命令5:UPDATE[PlanParameter]SET Mode=@p0,DefaultValueString=@p1,ParameterID=@p2其中ID=@p3;@p0=1[Type:Int16(0)],@p1='0'[Type:string(4000)],@p2=2[Type:Int32(0)],@p3=1362[Type:Int32(0)];
匹配=注册匹配(样本);
字符串结果=match.Groups[“Query”].Value;
对于(int i=0;i
这很好用,但我相信有一种更干净整洁的方法。也许用不同的正则表达式


如果有任何帮助,我们将不胜感激。

这里有一个更紧凑的正则表达式方法:

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

替换:
${2}

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

请参见“替换”窗格的底部

输出:

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

解释

  • (@p\d+
    捕获
    @p
    中的括号和第1组的数字
  • 前瞻
    (?=.*\1([^\[]+)
    断言下面的内容是
  • *?
    匹配任何字符,直到
  • \1
    第1组匹配的内容(例如
    @p0
  • (=[^\[]+)
    中的括号将文本
    =
    捕获到第2组,所有字符都不是
    [
    (我们将其用作分隔符,以了解值何时结束。这是您的值
  • 或者…
    |
    我们还将匹配字符串的结尾,因为匹配时没有组2,所以替换的
    ${2}
    将取消它
  • 分号
  • 为了安全起见,负前瞻
    (?!.=@p\d)
    断言后面的不是任何字符,然后
    =@p
    +数字
  • *
    将分号和所有字符匹配到字符串的末尾
  • 替换字符串
    ${2}
    =
    和组2(值)
参考


+1尝试CaptureCollection:)Toda raba,很高兴它能帮上忙。:)哇,谢谢,这正是我要找的!我对正则表达式非常熟悉,我会仔细研究你的:)
command 5:UPDATE [PlanParameter] SET Mode = 1 , DefaultValueString = '0' , ParameterID = 2 WHERE ID = 1362 
String replaced = Regex.Replace(yourString, @"= (@p\d+)(?=.*?\1 (= [^\[]+))|;(?!.*= @p\d).*", "${2}");