Chỉ thay thế một số nhóm bằng Regex


190

Giả sử tôi có regex sau:

-(\d+)-

và tôi muốn thay thế, sử dụng C #, Nhóm 1 (\d+)bằng AA, để có được:

-AA-

Bây giờ tôi đang thay thế nó bằng cách sử dụng:

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

Nhưng tôi không thực sự thích điều này, bởi vì nếu tôi thay đổi mẫu để phù hợp _(\d+)_thay vào đó, tôi cũng sẽ phải thay đổi chuỗi thay thế _AA_và điều này trái với nguyên tắc DRY.

Tôi đang tìm kiếm một cái gì đó như:

Giữ văn bản phù hợp chính xác như thế nào, nhưng thay đổi Nhóm 1 theo this textvà Nhóm 2 bằng another text...

Chỉnh sửa:
Đó chỉ là một ví dụ. Tôi chỉ tìm kiếm một cách chung để làm những gì tôi đã nói ở trên.

Nó nên hoạt động cho:

anything(\d+)more_text và bất kỳ mô hình bạn có thể tưởng tượng.

Tất cả những gì tôi muốn làm là chỉ thay thế các nhóm và giữ phần còn lại của trận đấu.

Câu trả lời:


306

Một ý tưởng tốt có thể là gói gọn tất cả mọi thứ trong các nhóm, bất kể có cần xác định chúng hay không. Bằng cách đó bạn có thể sử dụng chúng trong chuỗi thay thế của bạn. Ví dụ:

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

hoặc sử dụng MatchEvaluator:

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

Một cách khác, hơi lộn xộn, có thể là sử dụng lookbehind / lookahead:

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


17
Tôi đã chỉnh sửa câu trả lời của bạn để cung cấp thêm thông tin, nhưng những gì bạn nói là hoàn toàn chính xác. Không biết làm thế nào tôi bỏ lỡ rằng tôi có thể đặt mọi thứ trong các nhóm, bất kể có sử dụng chúng hay không :) . Theo tôi, giải pháp đó tốt hơn và sạch hơn nhiều so với sử dụng lookahead và lookbehinds.
Oscar Mederos

Lỗi đánh máy nhỏ, mẫu thay thế của bạn phải là $ 1AA $ 3
Myster

1
Để làm việc này, tôi phải thêm .Valuevào m.Groups[1]v.v.
jbeldock

10
Cũng đáng chú ý - nếu văn bản thay thế của bạn bắt đầu bằng một số, giải pháp đầu tiên ("$ 1AA $ 3") sẽ không hoạt động như dự định!
Bertie

2
@OscarMederos bạn cũng có thể sử dụng các nhóm không chụp - tốt cho các nhóm bạn không sử dụng. Trong (?:foo)(bar), $1sẽ thay thế bar. biết thêm chi tiết
Patrick

34

Bạn có thể làm điều này bằng cách sử dụng lookahead và lookbehind :

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

19

Tôi cũng có nhu cầu này và tôi đã tạo phương thức mở rộng sau cho nó:

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

Sử dụng:

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

Kết quả:

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

13

Nếu bạn không muốn thay đổi mẫu của mình, bạn có thể sử dụng thuộc tính Chỉ số nhóm và Độ dài của nhóm phù hợp.

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;

Xin lưu ý rằng điều này giả định và sẽ chỉ hoạt động cho lần xuất hiện đầu tiên của trận đấu.
Bartosz

5

Đây là một tùy chọn sạch đẹp khác mà không yêu cầu thay đổi mẫu của bạn.

        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

đi qua mã hóa dưới đây để có được sự thay thế nhóm riêng biệt.

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.