Ich brauche einen Weg, um dies zu haben:
"test, and test but not testing. But yes to test".Replace("test", "text")
gib dies zurück:
"text, and text but not testing. But yes to text"
Grundsätzlich möchte ich ganze Wörter ersetzen, aber keine Teilübereinstimmungen.
HINWEIS: Ich muss dafür VB verwenden (SSRS 2008-Code), aber C # ist meine normale Sprache, daher sind die Antworten in beiden Sprachen in Ordnung.
Antworten:
Ein Regex ist der einfachste Ansatz:
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);
Der wichtige Teil des Musters ist das
\b
Metazeichen, das an Wortgrenzen übereinstimmt. Wenn Sie die Groß- und Kleinschreibung nicht berücksichtigen müssenRegexOptions.IgnoreCase
:Regex.Replace(input, pattern, replace, RegexOptions.IgnoreCase);
quelle
\b
ist Regex für Wortgrenzen sprechen.static string ReplaceFullWords( string input, string from, string to) { if (input == null) { return null; } return Regex.Replace(input, "\\b" + Regex.Escape(from) + "\\b", to); }
string pattern = "\\btest\\b";
Ich habe eine Funktion erstellt (siehe Blog-Beitrag hier ), die den von Ahmad Mageed vorgeschlagenen regulären Ausdruck umschließt
/// <summary> /// Uses regex '\b' as suggested in /programming/6143642/way-to-have-string-replace-only-hit-whole-words /// </summary> /// <param name="original"></param> /// <param name="wordToFind"></param> /// <param name="replacement"></param> /// <param name="regexOptions"></param> /// <returns></returns> 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; }
quelle
Regex.Escape()
aufwordToFind
so Sonderzeichen als normale Zeichen interpretiert werden.Wie von Sga kommentiert, ist die Regex-Lösung nicht perfekt. Und ich denke auch nicht leistungsfreundlich.
Hier ist mein Beitrag:
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 (); } }
... mit Testfällen:
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" ) );
quelle
Ich möchte nur einen Hinweis zu diesem bestimmten Regex-Muster hinzufügen (wird sowohl in der akzeptierten Antwort als auch in der ReplaceWholeWord- Funktion verwendet). Es funktioniert nicht, wenn das, was Sie ersetzen möchten, kein Wort ist .
Hier ein Testfall:
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); } }
(bereit, Code zu versuchen: http://ideone.com/2Nt0A )
Dies muss besonders berücksichtigt werden, wenn Sie Stapelübersetzungen durchführen (wie ich es für einige i18n-Arbeiten getan habe).
quelle
Wenn Sie definieren möchten, aus welchen Zeichen ein Wort besteht, z. B. "_" und "@"
Sie könnten meine (vb.net) Funktion verwenden:
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
Prüfung
Replace_Whole_Word("We need to replace words tonight. Not to_day and not too well to", "to", "xxx")
Ergebnis
"We need xxx replace words tonight. Not to_day and not too well xxx"
quelle
Ich mag Regex nicht, weil es langsam ist. Meine Funktion ist schneller.
public static string ReplaceWholeWord(this string text, string word, string bywhat) { static bool IsWordChar(char c) => char.IsLetterOrDigit(c) || c == '_'; StringBuilder sb = null; int p = 0, j = 0; while (j < text.Length && (j = text.IndexOf(word, j, StringComparison.Ordinal)) >= 0) if ((j == 0 || !IsWordChar(text[j - 1])) && (j + word.Length == text.Length || !IsWordChar(text[j + word.Length]))) { sb ??= new StringBuilder(); sb.Append(text, p, j - p); sb.Append(bywhat); j += word.Length; p = j; } else j++; if (sb == null) return text; sb.Append(text, p, text.Length - p); return sb.ToString(); }
quelle
Sie könnten die Zeichenfolge.replace verwenden
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();
quelle
replace
wird sich nicht änderntesting
,texting
wie in der Frage gestellt?