10

I need to replace a string where it follows a specific string and some varying data. I need to keep the beginning and the middle and just replace the end. When I tried the code below, it replaces only the last occurance. I have tried switching to a non greedy match but then it doesn't find it. The middle could contain new lines as well spaces, letters and numbers.

String s = "Beginning of story. Keep this sentence. Old ending.\n";
s += s;
s += s;
s1 = Regex.Replace(s, @"Beginning of story. ([\s\S]*) Old ending.", "Beginning of story. " + @"$1" + " New ending.", RegexOptions.Multiline | RegexOptions.IgnoreCase);

The result is this:
Beginning of story. Keep this sentence. Old ending.
Beginning of story. Keep this sentence. Old ending.
Beginning of story. Keep this sentence. Old ending.
Beginning of story. Keep this sentence. New ending.

How do I replace every occurance of "Old ending."

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
BrianK
  • 2,357
  • 3
  • 32
  • 41
  • Try adding a `$` at the end of your pattern - should match the end of each line, given your `Multiline` option. – zimdanen Jun 21 '13 at 18:56
  • Related: http://stackoverflow.com/q/2301285/785745 – Kendall Frey Jun 21 '13 at 19:06
  • A non-greedy match should take care of it. Could you show what you've tried? – Kendall Frey Jun 21 '13 at 19:08
  • I tried this. It doesn't replace anything s1 = Regex.Replace(s, @"Beginning of story. ([\s\S]?) Old ending.", "Beginning of story. " + @"$1" + " New ending.", RegexOptions.Multiline | RegexOptions.IgnoreCase); – BrianK Jun 21 '13 at 19:12
  • This is just an example. In my real data what I want to replace is not at the end of a line. but that gives me an idea to try. – BrianK Jun 21 '13 at 19:15
  • 1
    @BrianK: I think a non-greedy match would be `*?`, not just `?` - `?` on its own is `0 or 1`. – zimdanen Jun 21 '13 at 19:16
  • One thing to look out for is to escape your `.`'s as well. It probably wont matter because in most cases it will just consume the literal `.` anyway, but it is still a good idea to use `[.]` or `\.` instead. – Cemafor Jun 21 '13 at 19:22
  • *? for the non-greedy match worked. Thanks so much. – BrianK Jun 21 '13 at 20:43

2 Answers2

14

I think Kendall is bang on with the related link, a non greedy match e.g.

s1 = Regex.Replace(s, @"Beginning of story. ([\s\S]*?) Old ending.", "Beginning of story. " + @"$1" + " New ending.", RegexOptions.Multiline | RegexOptions.IgnoreCase);

Should do the trick.

Edit:

You should also be able to change the pattern inside your capture region to be: .* where . will match any character except the newline character.

Chris
  • 8,268
  • 3
  • 33
  • 46
7

If all you want to do is replace Old ending with New ending, why don't you just use good old string.Replace? Will be easier and faster than using regex

String s = "Beginning of story. Keep this sentence. Old ending.\n";
s.Replace("Old ending", "New ending");

Update: To replace Old ending wherever it is preceded with Begining of story... then use this regex (?<=Beginning of story.*?)Old ending, play around with this if you have slight variations, but this should get you there

Regex.Replace(s, @"(?<=Beginning of story.*?)Old ending", "New ending");

This basically says, find and replace "Old ending" with "New ending", but only if it starts with "Beginning of story blah blah blah"

Jason
  • 3,844
  • 1
  • 21
  • 40
  • 1
    I only want to replace "old ending" where it occurs after "Beginning of story". If it occurred outside of that pattern, I don't want to replace it. – BrianK Jun 21 '13 at 19:10
  • @BrianK see updated answer, the pattern I provided should do the trick – Jason Jun 21 '13 at 19:30