¿Cómo reemplazo la * primera instancia * de una cadena en .NET?

108

Quiero reemplazar la primera aparición en una cadena determinada.

¿Cómo puedo lograr esto en .NET?

Adiós StackExchange
fuente
Por favor, haga publicaciones claras que la gente pueda entender. También edité este para ti. Debería haber especificado un idioma al menos aquí.
GEOCHET
Por supuesto, nunca se reemplaza ... siempre es una nueva cadena que contiene la original con el texto reemplazado. Esto se debe a que las cuerdas son inmutables.
Pablo Marambio
Probé el método `String.Replace ()`. pero reemplaza todo el "AA" con "XQ"
Thorin Oakenshield
2
esta pregunta - stackoverflow.com/questions/141045/… - revela todo sobre lo que necesitas hacer
stack72
1
Nota: fusionando con otra pregunta similar que usaba "AA" => "XQ" como ejemplos para buscar / reemplazar.
Marc Gravell

Respuestas:

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

Ejemplo:

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

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

EDITAR : Como mencionó @itsmatt , también está Regex.Replace (String, String, Int32), que puede hacer lo mismo, pero probablemente sea más costoso en tiempo de ejecución, ya que utiliza un analizador con todas las funciones donde mi método hace una búsqueda y tres cadenas concatenaciones.

EDIT2 : si esta es una tarea común, es posible que desee convertir el método en un método de extensión:

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

Usando el ejemplo anterior, ahora es posible escribir:

str = str.ReplaceFirst("brown", "quick");
VVS
fuente
2
Interesante, ¿probó su suposición de que el enfoque de expresiones regulares es más caro en tiempo de ejecución? ¿Qué tal la velocidad? ¿Quizás la búsqueda usando Regex es más rápida que usando IndexOf?
mfloryan
Prefiero un poco la respuesta de @BilltheLizard que involucra Remove () e Insert () sobre este enfoque que involucra Substring (). ¿Existe alguna base para decir que uno es mejor que el otro?
JohnC
3
Atención: esto no funciona correctamente con Unicode que combina caracteres o ligaduras. Por ejemplo, ReplaceFirst("oef", "œ", "i")devuelve incorrectamente "ief" en lugar de "if". Consulte esta pregunta para obtener más información.
Michael Liu
2
ReSharper advierte String.IndexOf is culture specific.. Más robusto para actualizar int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango
64

Como dijo itsmatt , Regex.Replace es una buena opción para esto, sin embargo, para que su respuesta sea más completa, la completaré con una muestra de código:

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

El tercer parámetro, establecido en 1 en este caso, es el número de apariciones del patrón de expresiones regulares que desea reemplazar en la cadena de entrada desde el principio de la cadena.

Tenía la esperanza de que esto se pudiera hacer con un Regex estático. Reemplace la sobrecarga, pero desafortunadamente parece que necesita una instancia de Regex para lograrlo.

Wes Haggard
fuente
1
Eso funciona para literal "foo", pero querrás un new Regex(Regex.Escape("foo"))figurativo "foo".
ruffin
17

Eche un vistazo a Regex.Replace .

itsmatt
fuente
2
Específicamente, el método Regex.Replace (String, String, Int32) hará el truco y es realmente conciso.
itsmatt
15

Teniendo en cuenta el "solo primero", quizás:

int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
     input.Substring(index + 2);

?

O más generalmente:

public static string ReplaceFirstInstance(this string source,
    string find, string replace)
{
    int index = source.IndexOf(find);
    return index < 0 ? source : source.Substring(0, index) + replace +
         source.Substring(index + find.Length);
}

Luego:

string output = input.ReplaceFirstInstance("AA", "XQ");
Marc Gravell
fuente
11
using System.Text.RegularExpressions;

RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);

encontrará primero Fen InputStringy lo reemplazará con R.

Deenesh
fuente
2
Lo simplifiqué a una sola línea porresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth
La mejor respuesta aquí (junto con cjbarth)
Todd Vance
8

Método de extensión C # que hará esto:

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

Disfrutar

mortenbpost
fuente
¡Gracias! Modifiqué esto para hacer un método de extensión "RemoveFirst" que ... elimina la primera aparición de un carácter de una cadena.
pbh101
4
Esto fallará si oldValue no es parte de la cadena.
VVS
8

En la sintaxis de C #:

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

Y como también hay que considerar VB.NET, me gustaría ofrecer:

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
Anthony Potts
fuente
4

Asume que AAsolo necesita ser reemplazado si está al comienzo de la cadena:

var newString;
if(myString.StartsWith("AA"))
{
  newString ="XQ" + myString.Substring(2);
}

Si necesita reemplazar la primera aparición de AA, ya sea que la cadena comience con él o no, vaya con la solución de Marc.

Oded
fuente
3

Una de las sobrecargas de Regex.Replacetoma un intpara "El número máximo de veces que puede ocurrir el reemplazo". Obviamente, usar el Regex.Replacereemplazo de texto sin formato puede parecer excesivo, pero ciertamente es conciso:

string output = (new Regex("AA")).Replace(input, "XQ", 1);
AakashM
fuente
2

Para cualquiera a quien no le importe una referencia Microsoft.VisualBasic, existe el ReplaceMétodo :

string result = Microsoft.VisualBasic.Strings.Replace("111", "1", "0", 2, 1); // "101"
Slai
fuente
1

Este ejemplo abstrae las subcadenas (pero es más lento), pero probablemente sea mucho más rápido que una expresión regular:

var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];

fuente
-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }

fuente