Ganti hanya beberapa grup dengan Regex


191

Misalkan saya memiliki regex berikut:

-(\d+)-

dan saya ingin mengganti, menggunakan C #, Grup 1 (\d+)dengan AA, untuk mendapatkan:

-AA-

Sekarang saya menggantinya menggunakan:

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

Tapi saya tidak terlalu suka ini, karena jika saya mengubah pola untuk mencocokkan _(\d+)_sebagai gantinya, saya harus mengganti string pengganti _AA_juga, dan ini bertentangan dengan prinsip KERING.

Saya mencari sesuatu seperti:

Pertahankan teks yang cocok persis seperti apa adanya, tetapi ubah Grup 1 dengan this textdan Grup 2 dengan another text...

Sunting:
Itu hanya contoh. Saya hanya mencari cara umum untuk melakukan apa yang saya katakan di atas.

Ini harus bekerja untuk:

anything(\d+)more_text dan pola apa pun yang dapat Anda bayangkan.

Yang ingin saya lakukan adalah mengganti hanya grup, dan mempertahankan sisa pertandingan.

Jawaban:


307

Ide yang bagus adalah merangkum semua yang ada di dalam kelompok, tidak peduli apakah perlu mengidentifikasi mereka atau tidak. Dengan begitu Anda bisa menggunakannya dalam string pengganti Anda. Sebagai contoh:

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

atau menggunakan MatchEvaluator:

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

Cara lain, sedikit berantakan, bisa menggunakan lookbehind / lookahead:

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


17
Saya mengedit jawaban Anda untuk memberikan lebih banyak informasi, tetapi apa yang Anda katakan sepenuhnya benar. Tidak tahu bagaimana saya merindukan bahwa saya bisa memasukkan semuanya ke dalam kelompok, tidak peduli apakah akan menggunakannya atau tidak :) . Menurut pendapat saya, solusi itu jauh lebih baik dan lebih bersih daripada menggunakan lookahead dan lookbehinds.
Oscar Mederos

kesalahan ketik kecil, pola penggantian Anda harus $ 1AA $ 3
Myster

1
Agar ini berfungsi, saya harus menambahkan .Valueke m.Groups[1]dll.
jbeldock

11
Juga patut dicatat - jika teks pengganti Anda dimulai dengan angka, solusi pertama ("$ 1AA $ 3") tidak akan berfungsi sebagaimana mestinya!
Bertie

2
@OscarMederos Anda juga dapat menggunakan grup yang tidak menangkap - bagus untuk grup yang tidak Anda gunakan. Dalam (?:foo)(bar), $1akan diganti bar. lebih detail
Patrick


19

Saya juga membutuhkan ini dan saya membuat metode ekstensi berikut untuk itu:

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

Pemakaian:

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

Hasil:

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

Saya suka implementasi ini tetapi tidak menggantikan beberapa pertandingan. Saya memposting versi yang tidak
Vladimir

13

Jika Anda tidak ingin mengubah pola, Anda dapat menggunakan properti Indeks Grup dan Panjang grup yang cocok.

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;

Harap dicatat bahwa ini mengasumsikan dan hanya akan berfungsi untuk kemunculan pertama pertandingan.
Bartosz

5

Berikut ini adalah opsi bersih lain yang bagus yang tidak perlu mengubah pola Anda.

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

0

buka kode di bawah ini untuk mendapatkan penggantian kelompok yang terpisah.

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

Ini adalah versi yang mirip dengan Daniel tetapi mengganti beberapa kecocokan:

public static string ReplaceGroup(string input, string pattern, RegexOptions options, string groupName, string replacement)
{
    Match match;
    while ((match = Regex.Match(input, pattern, options)).Success)
    {
        var group = match.Groups[groupName];

        var sb = new StringBuilder();

        // Anything before the match
        if (match.Index > 0)
            sb.Append(input.Substring(0, match.Index));

        // The match itself
        var startIndex = group.Index - match.Index;
        var length = group.Length;
        var original = match.Value;
        var prior = original.Substring(0, startIndex);
        var trailing = original.Substring(startIndex + length);
        sb.Append(prior);
        sb.Append(replacement);
        sb.Append(trailing);

        // Anything after the match
        if (match.Index + match.Length < input.Length)
            sb.Append(input.Substring(match.Index + match.Length));

        input = sb.ToString();
    }

    return input;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.