正则表达式替换重复捕获

Posted

技术标签:

【中文标题】正则表达式替换重复捕获【英文标题】:Regex Replace repeated captures 【发布时间】:2014-08-30 11:24:40 【问题描述】:

我正在创建一个 log4net 附加程序,它生成准备执行的 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+\)\],? ?)+)

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

我希望整个替换都由 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);
    

这非常有效,但我确信有一种更干净整洁的方法可以做到这一点。也许使用不同的正则表达式?

任何帮助将不胜感激。

【问题讨论】:

+1 用于试验 CaptureCollection :) 【参考方案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 组文字 =,所有不是 [ 的字符(我们将其用作分隔符以了解您的值何时结束。这是您的值李> 或者...|我们也将匹配字符串的结尾,并且由于匹配时没有第2组,替换$2将取消它 ;分号 为了安全起见,负前瞻 (?!.*= @p\d) 断言后面的不是任何字符,然后是 = @p + 数字 .* 匹配分号和字符串末尾的所有字符 替换字符串 $2= 和 Group 2(值)

参考

Lookahead and Lookbehind Zero-Length Assertions Mastering Lookahead and Lookbehind Everything about Regex Capture Groups

【讨论】:

Toda raba,很高兴它有帮助。 :) 哇,谢谢,正是我正在寻找的!我是 Regex 的新手,我会仔细研究你的:)

以上是关于正则表达式替换重复捕获的主要内容,如果未能解决你的问题,请参考以下文章

js正则表达式替换捕获内容

量词可以用于R中的正则表达式替换吗?

15.python正则匹配 元字符转义重复或捕获分组断言:零度断言负向零宽断言贪婪非贪婪引擎选项

正则表达式在 HTML 中查找特定标签 [重复]

SQL查找和替换正则表达式捕获组限制?

使用捕获搜索和替换正则表达式