Ich muss eine Zeichenfolge suchen und alle Vorkommen von %FirstName%
und %PolicyAmount%
durch einen Wert aus einer Datenbank ersetzen . Das Problem ist, dass die Großschreibung von Vorname unterschiedlich ist. Das hindert mich daran, die String.Replace()
Methode anzuwenden. Ich habe Webseiten zu diesem Thema gesehen, die darauf hindeuten
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
Aber aus irgendeinem Grund , wenn ich versuche und ersetzen %PolicyAmount%
mit $0
, nimmt der Ersatz nie statt. Ich gehe davon aus, dass es etwas damit zu tun hat, dass das Dollarzeichen ein reserviertes Zeichen in Regex ist.
Gibt es eine andere Methode, die ich verwenden kann, bei der die Eingabe nicht bereinigt wird, um mit Regex-Sonderzeichen umzugehen?
Antworten:
Von MSDN
$ 0 - "Ersetzt den letzten Teilstring, der mit der Gruppennummernnummer (dezimal) übereinstimmt."
In regulären .NET-Ausdrücken ist Gruppe 0 immer die gesamte Übereinstimmung. Für ein buchstäbliches $ müssen Sie
quelle
Scheint, als
string.Replace
hätte es eine Überladung, die einStringComparison
Argument braucht . Da dies nicht der Fall ist, können Sie Folgendes ausprobieren:quelle
ReplaceString
zuReplace
.oldValue == newValue == ""
.ReplaceString("œ", "oe", "", StringComparison.InvariantCulture)
wirftArgumentOutOfRangeException
.Eine Art verwirrende Gruppe von Antworten, zum Teil, weil der Titel der Frage tatsächlich viel größer ist als die spezifische Frage, die gestellt wird. Nach dem Durchlesen bin ich mir nicht sicher, ob eine Antwort ein paar Änderungen davon entfernt ist, all die guten Sachen hier zu assimilieren, also dachte ich mir, ich würde versuchen, es zusammenzufassen.
Hier ist eine Erweiterungsmethode, die meiner Meinung nach die hier genannten Fallstricke vermeidet und die am weitesten verbreitete Lösung bietet.
So...
"œ".ReplaceCaseInsensitiveFind("oe", "")
obwohl er vielleicht ein etwas anderes Verhalten im Sinne hatte.Leider ist der Kommentar von @HA, den Sie zu
Escape
allen drei haben, nicht korrekt . Der Anfangswert undnewValue
muss nicht sein.Hinweis: Sie müssen jedoch
$
s in dem neuen Wert, den Sie einfügen, maskieren, wenn sie Teil eines Markers sind, der als "erfasster Wert" erscheint . Somit sind die drei Dollarzeichen im Regex.Replace im Regex.Replace enthalten. Ohne das bricht so etwas ..."This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
Hier ist der Fehler:
Ich weiß, dass Leute, die mit Regex vertraut sind, das Gefühl haben, dass ihre Verwendung Fehler vermeidet, aber ich bin oft immer noch daran interessiert, Zeichenfolgen zu schnüffeln (aber erst, nachdem ich Spolsky über Codierungen gelesen habe ), um absolut sicher zu sein, dass Sie das bekommen, was Sie haben bestimmt für wichtige Anwendungsfälle. Erinnert mich ein wenig an Crockford über " unsichere reguläre Ausdrücke ". Zu oft schreiben wir reguläre Ausdrücke, die zulassen, was wir wollen (wenn wir Glück haben), aber ungewollt mehr zulassen (z. B. Is
$10
in meinem neuen regulären Ausdruck oben wirklich ein gültiger "Capture Value" -String?), Weil wir nicht nachdenklich genug waren . Beide Methoden haben Wert und beide fördern unterschiedliche Arten von unbeabsichtigten Fehlern. Komplexität ist oft leicht zu unterschätzen.Dieses seltsame
$
Entkommen (und das entkamRegex.Escape
nicht den erfassten Wertemustern, wie$0
ich es bei Ersatzwerten erwartet hätte) machte mich für eine Weile verrückt. Die Programmierung ist schwierig (c) 1842quelle
Hier ist eine Erweiterungsmethode. Ich bin mir nicht sicher, wo ich es gefunden habe.
quelle
Die einfachste Methode scheint einfach die Ersetzungsmethode zu verwenden, die im Lieferumfang von .Net enthalten ist und seit .Net 1.0 verfügbar ist:
Um diese Methode verwenden zu können, müssen Sie der Assembly Microsoft.VisualBasic einen Verweis hinzufügen. Diese Assembly ist ein Standardbestandteil der .NET-Laufzeit, kein zusätzlicher Download oder als veraltet markiert.
quelle
C. Dragon 76
hat wie erwartet funktioniert.quelle
Inspiriert von der Antwort von cfeduke habe ich diese Funktion erstellt, die IndexOf verwendet, um den alten Wert in der Zeichenfolge zu finden und ihn dann durch den neuen Wert zu ersetzen. Ich habe dies in einem SSIS-Skript verwendet, das Millionen von Zeilen verarbeitet, und die Regex-Methode war viel langsamer als diese.
quelle
Erweitern Sie die beliebte Antwort von C. Dragon 76 , indem Sie seinen Code in eine Erweiterung verwandeln, die die Standardmethode überlastet
Replace
.quelle
Basierend auf Jeff Reddys Antwort mit einigen Optimierungen und Validierungen:
quelle
eine Version ähnlich der von C. Dragon, aber wenn Sie nur einen einzigen Ersatz benötigen:
quelle
Hier ist eine weitere Option zum Ausführen von Regex-Ersetzungen, da nicht viele Leute zu bemerken scheinen, dass die Übereinstimmungen die Position innerhalb der Zeichenfolge enthalten:
quelle
quelle
Die Methode für reguläre Ausdrücke sollte funktionieren. Sie können jedoch auch die Zeichenfolge aus der Datenbank in Kleinbuchstaben, die% -Variablen% in Kleinbuchstaben und dann die Positionen und Längen in der Zeichenfolge in Kleinbuchstaben aus der Datenbank suchen. Denken Sie daran, dass sich die Positionen in einer Zeichenfolge nicht ändern, nur weil sie in einem niedrigeren Gehäuse angeordnet sind.
Wenn Sie dann eine Schleife verwenden, die in umgekehrter Reihenfolge abläuft (es ist einfacher, wenn Sie dies nicht tun, müssen Sie die Anzahl der Punkte, zu denen sich spätere Punkte bewegen, laufen lassen), entfernen Sie die% -Variablen% nach ihrer Position und aus Ihrer nicht untergeordneten Zeichenfolge aus der Datenbank Länge und geben Sie die Ersatzwerte ein.
quelle
(Da jeder einen Versuch macht). Hier ist meine Version (mit Nullprüfungen und korrekter Eingabe und Ersetzung) ** Inspiriert aus dem Internet und anderen Versionen:
Verwendungszweck:
quelle
Lassen Sie mich meinen Fall machen und dann können Sie mich in Stücke reißen, wenn Sie möchten.
Regex ist nicht die Antwort auf dieses Problem - relativ gesehen zu langsam und speicherhungrig.
StringBuilder ist viel besser als String Mangling.
Da dies eine ergänzende Erweiterungsmethode sein wird, halte
string.Replace
ich es für wichtig, die Funktionsweise anzupassen. Daher ist es wichtig, Ausnahmen für dieselben Argumentprobleme auszulösen, wie die Rückgabe der ursprünglichen Zeichenfolge, wenn keine Ersetzung vorgenommen wurde.Ich glaube, dass ein StringComparison-Parameter keine gute Idee ist. Ich habe es versucht, aber der ursprünglich von Michael-Liu erwähnte Testfall zeigte ein Problem:
Während IndexOf übereinstimmt, besteht eine Nichtübereinstimmung zwischen der Länge der Übereinstimmung in der Quellzeichenfolge (1) und oldValue.Length (2). Dies manifestierte sich darin, dass IndexOutOfRange in einigen anderen Lösungen verursacht wurde, als oldValue.Length zur aktuellen Übereinstimmungsposition hinzugefügt wurde und ich keinen Weg fand, dies zu umgehen. Da Regex ohnehin nicht mit dem Fall übereinstimmt, habe ich die pragmatische Lösung gewählt, nur
StringComparison.OrdinalIgnoreCase
für meine Lösung zu verwenden.Mein Code ähnelt anderen Antworten, aber meine Wendung ist, dass ich nach einer Übereinstimmung suche, bevor ich mir die Mühe mache, eine zu erstellen
StringBuilder
. Wenn keine gefunden wird, wird eine möglicherweise große Zuordnung vermieden. Der Code wird danndo{...}while
eher zu einem als zu einemwhile{...}
Ich habe einige umfangreiche Tests mit anderen Antworten durchgeführt und diese kamen etwas schneller heraus und verbrauchten etwas weniger Speicher.
quelle