How do I replace the *first instance* of a string in .NET?

Viewed 74696

I want to replace the first occurrence in a given string.

How can I accomplish this in .NET?

15 Answers
string ReplaceFirst(string text, string search, string replace)
{
  int pos = text.IndexOf(search);
  if (pos < 0)
  {
    return text;
  }
  return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}

Example:

string str = "The brown brown fox jumps over the lazy dog";

str = ReplaceFirst(str, "brown", "quick");

EDIT: As @itsmatt mentioned, there's also Regex.Replace(String, String, Int32), which can do the same, but is probably more expensive at runtime, since it's utilizing a full featured parser where my method does one find and three string concatenations.

EDIT2: If this is a common task, you might want to make the method an extension method:

public static class StringExtension
{
  public static string ReplaceFirst(this string text, string search, string replace)
  {
     // ...same as above...
  }
}

Using the above example it's now possible to write:

str = str.ReplaceFirst("brown", "quick");

As itsmatt said Regex.Replace is a good choice for this however to make his answer more complete I will fill it in with a code sample:

using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);             
// result = "bar1 foo2 foo3 foo4"

The third parameter, set to 1 in this case, is the number of occurrences of the regex pattern that you want to replace in the input string from the beginning of the string.

I was hoping this could be done with a static Regex.Replace overload but unfortunately it appears you need a Regex instance to accomplish it.

In C# syntax:

int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
    return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);

C# extension method that will do this:

public static class StringExt
{
    public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
    {
         int i = s.IndexOf(oldValue);
         return s.Remove(i, oldValue.Length).Insert(i, newValue);    
    } 
}

And because there is also VB.NET to consider, I would like to offer up:

Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
    Dim pos As Integer = text.IndexOf(search)
    If pos >= 0 Then
        Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
    End If
    Return text 
End Function

Updated extension method utilizing Span to minimize new string creation

    public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
        int index = source.IndexOf(search);
        if (index < 0) return source;
        var sourceSpan = source.AsSpan();
        return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
    }

With ranges and C# 10 we can do:

public static string ReplaceFirst(this string text, string search, string replace)
{
    int pos = text.IndexOf(search, StringComparison.Ordinal);
    return pos < 0 ? text : string.Concat(text[..pos], replace, text.AsSpan(pos + search.Length));
}
Related