![]() |
StringReplace-Funktion etwas aufbohren
Ich übergebe der einen String (Textdatei) und eine Zeichenkette zum ersetzen.
Aus 123 soll dann ABC werden, grob gesagt. Ich möchte aber gerne, dass nur jene 123 ersetzt werden, die nicht zwischen < und > stehen. "hallo 123 du" soll zu "hallo abc du" werden, aber "hier könnte <irgendetwas stehen 123. mir fällt gerade> nix ein" soll nicht zu "hier könnte <irgendetwas stehen abc. mir fällt gerade> nix ein" werden. Wie wäre soetwas möglich? Das < und > muss nicht zwangsweise direkt vor oder hinter 123 stehen. Für Hilfe wäre ich sehr dankbar. |
AW: StringReplace-Funktion etwas aufbohren
ganz billig:
* mehrmals ersetzen * <OldPattern> durch einen Platzhalter * dann OldPattern durch NewPattern * und am Ende den Platzhalter zurück zu <OldPattern> in deinem StringReplace: * zwei mal suchen (PosEx) nach "<123>" und "123" * nur wenn der aktuelle Treffer nicht von Beiden gefunden wurde, dann ersetzen, ansonsten weitersuchen * oder nach OldPattern suchen * dann prüfen, ob < bzw. > davor/dahinter und nur ersetzen, wenn nicht Oder ganz banal mit RegEx, was Diesbezüglich bereits alles bietet. ![]() |
AW: StringReplace-Funktion etwas aufbohren
Es ist ja nicht <123> was ich suche. Vor und hinter dem 123 zum < und > kann noch viel anderer Kram stehen. Sonst wäre es ja einfach.
Zitat:
Ganz grob erklärt sollen Vorkommen nicht ersetzt werden, wenn die sich innerhalb von html tag klammern befinden. Das kann aber auch mal ein img mit base64-kodierung sein. Und da habe ich keine Ahnung wie man sowas auch nur annähernd performant umsetzen könnte. |
AW: StringReplace-Funktion etwas aufbohren
Interessante Thematik.
Meine Theorie: 1. Original String-Kopie per Pos() nach "<" suchen lassen 2. Original String-Kopie von 1 bis #1 in einen neuen kopieren 3. diese neue kopie per StringReplace bearbeiten 4. per Pos() nach ">" suchen 5. diesen mini-string an #3 anheften 6. Original String-Kopie von 1 bis #4 löschen 7. wiederhole ab #1 |
AW: StringReplace-Funktion etwas aufbohren
Das klingt funktionabel. Es handelt sich hierbei um eine HTML-Datei.
Es können in so einer Datei gerne mehrere base64-img-tags auftauchen und dazu noch normale html-tags. Ich habe schon überlegt in den Dateien gewisse Abschnitte mit eigenen html-tags zu markieren (ignore-begin, ignore-end) und sowas aber das wäre im Prinzip dasselbe wie mit < und >. |
AW: StringReplace-Funktion etwas aufbohren
eine html datei kann man doch als xml reinladen und dann in den nodes stringreplace anwenden oder täusche ich mich? (ich mach zu selten etwas mit delphi und html, sorry)
|
AW: StringReplace-Funktion etwas aufbohren
Nein, nur Strict-HTML wäre kompatibel zu XML.
Aber es gibt auch HTML-Komponenten für Delphi. nochmal: lass das rumgepfusche * entweder eine HTML-Komponente, welche genau für sowas gedacht ist * oder RegEx, was durch komplexere Regeln mehr kann ![]() Echt mal, warum will sich jeder die Arbeit schwerer machen, als es sein muß? Oder fummelst du durm Ändern eines Pixels in einem TFileStream rum, anstatt im TBitmap.Canvas? |
AW: StringReplace-Funktion etwas aufbohren
Zitat:
![]() |
AW: StringReplace-Funktion etwas aufbohren
Ich lade die HTML-Datei in den HtmlViewer. XML bringt mir am Ende leider nichts.
|
AW: StringReplace-Funktion etwas aufbohren
Ja, darum zuerst HTML-Komponente. :zwinker:
Ansonsten bietet RegEx.Replace das, was jemand im StringReplace suchen wollte. |
AW: StringReplace-Funktion etwas aufbohren
Kannst du mir da auf die Sprünge helfen?
Wenn ich mir Punkte für RegEx geben müsste, hätte ich 0 von 10. Bei Regex101.com: abcd <img ganzvielblödsinnabcdefghistehthier > efghi |
AW: StringReplace-Funktion etwas aufbohren
Anderer Vorschlag:
HTML in 'ne MemoryStream laden und zeichenweise in einen zweiten MemoryStream schreiben. Vor jedem < einen Zeilenumbruch schreiben. Hinter jedem > einen Zeilenumbruch schreiben. Alle übrigen Zeilenumbrüche durch ein Leerzeichen ersetzen. Zweiten MemoryStream in 'ne Stringliste laden. Diese Stringliste enthält nun nur noch Zeilen, die entweder ein HTML-Tag enthalten oder nur aus reinem Text bestehen. StringReplace nur in den Zeilen aus reinem Text ausführen. |
AW: StringReplace-Funktion etwas aufbohren
Wie füge ich denn beides wieder zusammen? Ich brauche am Ende alles zusammen quasi im Originalzustand.
|
AW: StringReplace-Funktion etwas aufbohren
Leerzeichen und Zeilenumbrüche stellen im HTML keine Veränderung dar.
|
AW: StringReplace-Funktion etwas aufbohren
Dann verstehe ich den Ansatz oben nicht und was mir diese zweite StringList bringen soll.
Zitat:
Weil wenn ich das StringReplace auf die StringList ausführe bringt mir das nichts. Ich muss das StringReplace direkt auf den HTML-Content des HtmlViewers ausführen. |
AW: StringReplace-Funktion etwas aufbohren
aber im HTML ist doch ein bild per
Delphi-Quellcode:
in einem TAG und wird somit nicht berührt?!
<img src="data:image/png;base64,...../>
|
AW: StringReplace-Funktion etwas aufbohren
Ich denke das klappt alles nicht. Das zeichenweise Durchgehen könnte sehr lange dauern, weil diese Prozedur auch 3x oder 4x die Sekunde aufgerufen werden kann.
|
AW: StringReplace-Funktion etwas aufbohren
Vielleicht so: (da hier jede menge Informationen zwecks Ablauf fehlen)
Einen Hashwert der HTML erzeugen und mit vorhandenem Hash abgleichen, wenn ungleich eine neue in-memory Datei wie von Delphi.Narium beschrieben erzeugen und anwenden, wenn gleich dann mache nichts. |
AW: StringReplace-Funktion etwas aufbohren
Ich durchsuche das Htmlviewer-Element (den HTML-Datei) live beim Eintippen in ein Eingabefeld.
Die Eingabe wird, wenn gefunden, markiert. Werden nun aber Vorkommen markiet die sich innerhalb eines HTML-Tags befinden, wird das Dokument zerstört. |
AW: StringReplace-Funktion etwas aufbohren
Ja, es wird zwar von RegEx bei HTML abgeraten, aber das liegt vorwiegend an der Verschachtelung von HTML-Tags und daß diese auch noch "defekt" sein dürfen können.
IMG hat aber keine untergeordnete TAGs und selbst bei Strict-HTML kann man das eventuelle schließende </img> ignorieren. Problematisch würde es nur, wenn zwischen <img und src= noch weitere Attribute vorkämen, aber wenn man das ausschließen kann, dann stört sowas ja nicht. :angle2: |
AW: StringReplace-Funktion etwas aufbohren
Verschachtelte HTML-Tags kann ich nicht ausschließen.
|
AW: StringReplace-Funktion etwas aufbohren
Ja, aber doch nicht innerhalb eines
Delphi-Quellcode:
<img ....>
Problem bei RegEx ist, dass man z.B. zu einem <td> nicht das schließende </td> "sicher" finden kann, bei einer unbekanten Anzahl an weiteren Tags innerhalb. Abgesehn davon, dass das Schließende sogar fehlen könnte. Aber genau dafür gibt es für HTML passende Komponenten, genauso, wie man für XML auch eine XML-Komponente und kein StringReplace verwendet. |
AW: StringReplace-Funktion etwas aufbohren
Nein das nicht.
|
AW: StringReplace-Funktion etwas aufbohren
Ich habe mir vor längerer Zeit mal einen Code gebastelt, der eingeklammerte Begriffe übergeht, und bei dem man zusätzlich bestimmen kann, wieviel Ersetzungen vorgenommen werden können. Nach längerem Suchen habe ich das Ding gefunden. Man braucht nur normale Klammern gegen spitze austauschen! Vielleicht hilft es. Wenn nicht, dann eben nicht.
Gruß DBR function XReplace(const s, OldPattern, NewPattern: string; Number: integer; IgnoreCase: Boolean; Auf: String = '('; Zu: String = ')'): string; var pc, ps, ph, x, z, lga, lgn, lgs: integer; c, v: string; begin lga := length(OldPattern); if (lga > 0) then begin lgn := length(NewPattern); z := 0; v := lowercase(OldPattern); lgs := length(s); try x := 1; while x <= lgs do begin c := copy(s, x, lga); pc := pos(Auf, c); ps := pos(Zu, copy(s, x + pc, maxint)); if (ps > 0) and (pc > 0) then begin ph := pos(Auf, copy(s, x + pc, maxint)); if (ph = 0) or (ph > ps) then begin Result := Result + copy(c, 1, pc); inc(x, pc); c := copy(s, x, ps); Result := Result + c; inc(x, ps); continue; end; end; if (c = OldPattern) or (IgnoreCase and (lowercase(c) = v)) then begin if lgn > 0 then begin Result := Result + NewPattern; end; inc(z); inc(x, lga); if z = Number then break; end else begin Result := Result + copy(c, 1, 1); inc(x); end; end; Result := Result + copy(s, x, lgs - pred(x)); except Result := 'FEHLER'; end; end else Result := s; end; // Beispiel 1: ergibt 'Versuch1<Versuch2< Test3 >Versuch4<Test5> Versuch' // da Test3 und Test 5 ordnungsgemäß in spitzen Klammern stehen procedure TForm1.Button1Click(Sender: TObject); var Wieoft: integer; Ignorcase: Boolean; begin Wieoft := -1; // Alle Vorkommen Ignorcase := True; // bei False würde nichts ersetzt ListBox1.items.add(XReplace('Test1<Test2< Test3 >Test4<Test5> Test', 'test', 'Versuch', Wieoft, Ignorcase, '<', '>')); end; // Beispiel 2: ergibt 'Versuch1<Versuch2< Test3 >Versuch4<Test5> Test' // da das letzte "Test" bereits der vierte zu ändernde Begriff wäre procedure TForm1.Button2Click(Sender: TObject); var Wieoft: integer; Ignorcase: Boolean; begin Wieoft := 3; // nur die ersten drei, die nicht in spitzen Klammern stehen Ignorcase := True; ListBox1.items.add(XReplace('Test1<Test2< Test3 >Test4<Test5> Test', 'test', 'Versuch', Wieoft, Ignorcase, '<', '>')); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz