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

标签 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 表达式?

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

最佳答案

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

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

替换:${2}

这将用它们的值替换所有参数并删除字符串的末尾。

请参阅 regex demo 底部的替换 Pane .

输出:

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 组, 所有不是 [ 的字符(我们将其用作分隔符以了解您的值(value)何时结束。这就是您的值(value)
  • 或者... |我们还将匹配字符串的末尾,并且由于匹配时没有第 2 组,因此替换 ${2}会解决的
  • ;分号
  • 为了安全起见,负前瞻(?!.*= @p\d)断言后面的不是任何字符 = @p + 数字
  • .*匹配分号和字符串末尾的所有字符
  • 替换字符串 ${2}=和第 2 组(值)

引用

关于c# - 正则表达式替换重复捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24653622/

相关文章:

sql - 通过多个参数和条件检测 SQL 孤岛

regex - 如何强制正则表达式捕获最大的匹配项?

python - 匹配美国电话号码的正则表达式

c# - C# async 和 Java ExecutorService 的区别

sql - MS SQL 如果是 12 月,如何获取下个月

c# - 强制使用自定义属性

java - hibernate -JPA : foreign key not set in ManyToOne relationship

regex - 如何在postgresql中将所有首字母转换为大写

c# - c# 客户端和 java 服务器之间的安全通信

c# - 解构 WPF 的几何对象