提问者:小点点

仅用正则表达式替换某些组


假设我有以下正则表达式:

-(\d+)-

我希望使用C#将组1(\d+)替换为aa,以获得:

-AA-

现在我用以下代码替换它:

var text = "example-123-example";
var pattern = @"-(\d+)-";
var replaced = Regex.Replace(text, pattern, "-AA-"); 

但我并不喜欢这样做,因为如果我更改模式以匹配_(\d+)_,那么我也将不得不将替换字符串更改为_aa_,这是违反DRY原则的。

我在找这样的东西:

保持匹配文本的原样,但按此文本更改组1,按另一文本更改组2.。。

编辑:
这只是一个示例。我只是在寻找一种通用的方法来做我上面所说的事情。

它应适用于:

任何(\d+)more_text以及您可以想象的任何模式。

我想要做的就是只替换小组,并保留其余的比赛。


共3个答案

匿名用户

一个好主意可能是在组内封装所有内容,无论是否需要标识它们。这样就可以在替换字符串中使用它们。例如:

var pattern = @"(-)(\d+)(-)";
var replaced = Regex.Replace(text, pattern, "$1AA$3"); 

或使用MatchEvaluator:

var replaced = Regex.Replace(text, pattern, m => m.Groups[1].Value + "AA" + m.Groups[3].Value);

另一种方式是使用lookbehind/lookahead,略显混乱:

(?<=-)(\d+)(?=-)

匿名用户

您可以使用lookahead和lookbehind执行此操作:

var pattern = @"(?<=-)\d+(?=-)";
var replaced = Regex.Replace(text, pattern, "AA"); 

匿名用户

我也需要这样做,为此创建了以下扩展方法:

public static class RegexExtensions
{
    public static string ReplaceGroup(
        this Regex regex, string input, string groupName, string replacement)
    {
        return regex.Replace(
            input,
            m =>
            {
                var group = m.Groups[groupName];
                var sb = new StringBuilder();
                var previousCaptureEnd = 0;
                foreach (var capture in group.Captures.Cast<Capture>())
                {
                    var currentCaptureEnd =
                        capture.Index + capture.Length - m.Index;
                    var currentCaptureLength =
                        capture.Index - m.Index - previousCaptureEnd;
                    sb.Append(
                        m.Value.Substring(
                            previousCaptureEnd, currentCaptureLength));
                    sb.Append(replacement);
                    previousCaptureEnd = currentCaptureEnd;
                }
                sb.Append(m.Value.Substring(previousCaptureEnd));

                return sb.ToString();
            });
    }
}

用法:

var input = @"[assembly: AssemblyFileVersion(""2.0.3.0"")][assembly: AssemblyFileVersion(""2.0.3.0"")]";
var regex = new Regex(@"AssemblyFileVersion\(""(?<version>(\d+\.?){4})""\)");


var result = regex.ReplaceGroup(input , "version", "1.2.3");

结果:

[assembly: AssemblyFileVersion("1.2.3")][assembly: AssemblyFileVersion("1.2.3")]