web-dev-qa-db-fra.com

Remplacer seulement certains groupes avec Regex

Supposons que j'ai la regex suivante:

-(\d+)-

et je veux remplacer, en utilisant C #, le groupe 1 (\d+) par AA, pour obtenir:

-AA-

Maintenant, je le remplace en utilisant:

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

Mais je n'aime pas trop cela, parce que si je change le motif pour qu'il corresponde à _(\d+)_, je devrai aussi changer la chaîne de remplacement par _AA_, et ceci contre le DRY principe.

Je cherche quelque chose comme:

Conservez le texte correspondant exactement tel qu'il est, mais changez le groupe 1 par this text et le groupe 2 par another text...

Edit:
C'était juste un exemple. Je cherche simplement un moyen générique de faire ce que j'ai dit ci-dessus.

Cela devrait fonctionner pour:

anything(\d+)more_text et tout motif que vous pouvez imaginer.

Tout ce que je veux faire est de ne remplacer que les groupes et de garder le reste du match.

171
Oscar Mederos

Une bonne idée pourrait être d'encapsuler tout ce qui se trouve à l'intérieur des groupes, qu'il soit nécessaire de les identifier ou non. De cette façon, vous pouvez les utiliser dans votre chaîne de remplacement. Par exemple:

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

ou en utilisant un MatchEvaluator:

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

Une autre façon, légèrement désordonnée, pourrait être d’utiliser un lookbehind/lookahead:

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

271
bluepnume

Vous pouvez le faire en utilisant lookahead and lookbehind :

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

J'en avais aussi besoin et j'ai créé la méthode d'extension suivante:

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();
            });
    }
}

Usage:

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");

Résultat:

[Assembly: AssemblyFileVersion("1.2.3")][Assembly: AssemblyFileVersion("1.2.3")]
16
Daniel Hilgarth

Si vous ne souhaitez pas modifier votre modèle, vous pouvez utiliser les propriétés Index de groupe et Longueur d'un groupe correspondant.

var text = "example-123-example";
var pattern = @"-(\d+)-";
var regex = new RegEx(pattern);
var match = regex.Match(text);

var firstPart = text.Substring(0,match.Groups[1].Index);    
var secondPart = text.Substring(match.Groups[1].Index + match.Groups[1].Length);
var fullReplace = firstPart + "AA" + secondPart;
13
Dick Verweij

Voici une autre option propre qui ne nécessite pas de changer de motif.

        var text = "example-123-example";
        var pattern = @"-(\d+)-";

        var replaced = Regex.Replace(text, pattern, (_match) =>
        {
            Group group = _match.Groups[1];
            string replace = "AA";
            return String.Format("{0}{1}{2}", _match.Value.Substring(0, group.Index - _match.Index), replace, _match.Value.Substring(group.Index - _match.Index + group.Length));
        });
3
curlyhairedgenius

consultez le codage ci-dessous pour obtenir le remplacement distinct du groupe.

new_bib = Regex.Replace(new_bib, @"(?s)(\\bibitem\[[^\]]+\]\{" + pat4 + @"\})[\s\n\v]*([\\\{\}a-zA-Z\.\s\,\;\\\#\\\$\\\%\\\&\*\@\\\!\\\^+\-\\\=\\\~\\\:\\\" + dblqt + @"\\\;\\\`\\\']{20,70})", delegate(Match mts)
                    {
                           var fg = mts.Groups[0].Value.ToString(); 
                           var fs = mts.Groups[1].Value.ToString();
                           var fss = mts.Groups[2].Value.ToString();
                               fss = Regex.Replace(fss, @"[\\\{\}\\\#\\\$\\\%\\\&\*\@\\\!\\\^+\-\\\=\\\~\\\:\\\" + dblqt + @"\\\;\\\`\\\']+", "");
                           return "<augroup>" + fss + "</augroup>" + fs;
                    }, RegexOptions.IgnoreCase);
0
BalaS