Modo per avere String.Replace colpisci solo “parole intere”

Ho bisogno di un modo per avere questo:

"test, and test but not testing. But yes to test".Replace("test", "text") 

restituisci questo:

 "text, and text but not testing. But yes to text" 

Fondamentalmente voglio sostituire le parole intere, ma non le corrispondenze parziali.

NOTA: Dovrò utilizzare VB per questo (codice SSRS 2008), ma C # è la mia lingua normale, quindi le risposte in entrambi sono soddisfacenti.

Una regex è l’approccio più semplice:

 string input = "test, and test but not testing. But yes to test"; string pattern = @"\btest\b"; string replace = "text"; string result = Regex.Replace(input, pattern, replace); Console.WriteLine(result); 

La parte importante del pattern è il metacarattere \b , che corrisponde ai limiti delle parole. Se hai bisogno che sia senza distinzione tra maiuscole e minuscole usa RegexOptions.IgnoreCase :

 Regex.Replace(input, pattern, replace, RegexOptions.IgnoreCase); 

Ho creato una funzione (vedi post di blog qui ) che avvolge l’espressione regolare , suggerita da Ahmad Mageed

 ///  /// Uses regex '\b' as suggested in https://stackoverflow.com/questions/6143642/way-to-have-string-replace-only-hit-whole-words ///  ///  ///  ///  ///  ///  static public string ReplaceWholeWord(this string original, string wordToFind, string replacement, RegexOptions regexOptions = RegexOptions.None) { string pattern = String.Format(@"\b{0}\b", wordToFind); string ret=Regex.Replace(original, pattern, replacement, regexOptions); return ret; } 

Come commentato da Sga, la soluzione regex non è perfetta. E immagino che non sia anche una performance amichevole.

Ecco il mio contributo:

 public static class StringExtendsionsMethods { public static String ReplaceWholeWord ( this String s, String word, String bywhat ) { char firstLetter = word[0]; StringBuilder sb = new StringBuilder(); bool previousWasLetterOrDigit = false; int i = 0; while ( i < s.Length - word.Length + 1 ) { bool wordFound = false; char c = s[i]; if ( c == firstLetter ) if ( ! previousWasLetterOrDigit ) if ( s.Substring ( i, word.Length ).Equals ( word ) ) { wordFound = true; bool wholeWordFound = true; if ( s.Length > i + word.Length ) { if ( Char.IsLetterOrDigit ( s[i+word.Length] ) ) wholeWordFound = false; } if ( wholeWordFound ) sb.Append ( bywhat ); else sb.Append ( word ); i += word.Length; } if ( ! wordFound ) { previousWasLetterOrDigit = Char.IsLetterOrDigit ( c ); sb.Append ( c ); i++; } } if ( s.Length - i > 0 ) sb.Append ( s.Substring ( i ) ); return sb.ToString (); } } 

… Con casi di test:

 String a = "alpha is alpha"; Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alphonse" ) ); Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alf" ) ); a = "alphaisomega"; Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) ); a = "aalpha is alphaa"; Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) ); a = "alpha1/alpha2/alpha3"; Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) ); a = "alpha/alpha/alpha"; Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alphonse" ) ); 

Voglio solo aggiungere una nota su questo particolare modello regex (usato sia nella risposta accettata che nella funzione ReplaceWholeWord ). Non funziona se quello che stai cercando di sostituire non è una parola .

Ecco un test:

 using System; using System.Text.RegularExpressions; public class Test { public static void Main() { string input = "doin' some replacement"; string pattern = @"\bdoin'\b"; string replace = "doing"; string result = Regex.Replace(input, pattern, replace); Console.WriteLine(result); } } 

(pronto a provare il codice: http://ideone.com/2Nt0A )

Questo deve essere preso in considerazione soprattutto se si stanno facendo traduzioni in batch (come ho fatto per alcuni lavori i18n).

Se si desidera definire quali caratteri costituiscono una parola, ad esempio “_” e “@”

potresti usare la mia funzione (vb.net):

  Function Replace_Whole_Word(Input As String, Find As String, Replace As String) Dim Word_Chars As String = "ABCDEFGHIJKLMNOPQRSTUVWYXZabcdefghijklmnopqrstuvwyxz0123456789_@" Dim Word_Index As Integer = 0 Do Until False Word_Index = Input.IndexOf(Find, Word_Index) If Word_Index < 0 Then Exit Do If Word_Index = 0 OrElse Word_Chars.Contains(Input(Word_Index - 1)) = False Then If Word_Index + Len(Find) = Input.Length OrElse Word_Chars.Contains(Input(Word_Index + Len(Find))) = False Then Input = Mid(Input, 1, Word_Index) & Replace & Mid(Input, Word_Index + Len(Find) + 1) End If End If Word_Index = Word_Index + 1 Loop Return Input End Function 

Test

 Replace_Whole_Word("We need to replace words tonight. Not to_day and not too well to", "to", "xxx") 

Risultato

 "We need xxx replace words tonight. Not to_day and not too well xxx" 

Potresti usare string.replace

 string input = "test, and test but not testing. But yes to test"; string result2 = input.Replace("test", "text"); Console.WriteLine(input); Console.WriteLine(result2); Console.ReadLine();