StringReplace mit Umlauten?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
enyaw_ecurb
Beiträge: 8
Registriert: Mi 4. Feb 2009, 00:21

StringReplace mit Umlauten?

Beitrag von enyaw_ecurb »

Nachdem ich jahrelang alle Kodierungsprobleme umschifft habe, bin ich im Moment etwas frustriert.

Ich suche lediglich ein StringReplace, das mit den utf8-strings aus lazarus zurechtkommt. Bisher war ich davon ausgegangen, dass es das täte, aber anscheinend habe ich mich geirrt.

Folgendes Beispiel:

Code: Alles auswählen

AnsiReplaceText('abcdßabcdßabcd', 'a', 'x') => 'xbcdßaxcdßabxd'
Mit einem 'scharfen S' scheint er die Ersetzungsstellen zu verschieben (mit ä,ü,ö funktioniert es aber irgendwie...).

Muss ich die Strings vorher konvertieren, mir wohlmöglich ein StringReplace für Widestrings schreiben? Gibt es da eine Lösung, mache ich irgendwas falsch?

Ich bin für jede Hilfe dankbar...

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Re: StringReplace mit Umlauten?

Beitrag von monta »

Wenn du statt AnsiTextReplace nur StringReplace nutzt, sollte es gehen:

Code: Alles auswählen

StringReplace('abcdßabcdßabcd', 'a', 'x', [rfReplaceAll])
Johannes

enyaw_ecurb
Beiträge: 8
Registriert: Mi 4. Feb 2009, 00:21

Re: StringReplace mit Umlauten?

Beitrag von enyaw_ecurb »

Ahh... Ich war sicher, ich hatte das schon ausprobiert ;-) Ich war auch sicher, dass AnsiReplaceText intern auf StringReplace umleitet...

Eine kurze Recherche (danke dabei auch für die schnelle Antwort) offenbart bei mir folgendes:

StrReplace ohne rfIgnoreCase (also AnsiReplaceStr) funktioniert...
StrReplace mit rfIgnoreCase (also AnsiReplaceText) haut nicht hin

Bug oder Feature? Leider brauche ich für meine Anwendung eigentlich letztere Variante...

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Re: StringReplace mit Umlauten?

Beitrag von monta »

dann probier mal:

Code: Alles auswählen

AnsiReplaceText(UTF8Decode('abcdßabcdßabcd'), 'a', 'x')
Falls du es auch wieder ausgeben willst in der LCL brauchst du auch noch UTF8Encode:

Code: Alles auswählen

ShowMessage(UTF8Encode(AnsiReplaceText(UTF8Decode('abcdßabcdßabcd'), 'a', 'x')));
Johannes

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: StringReplace mit Umlauten?

Beitrag von theo »

Nulla.
Ich wollte was sagen, was ich später dann doch nicht sagen wollte. Immerhin eine Gelegenheit ein paar Brocken italienisch bzw. Philosophie zu lernen (wenn ich den Eintrag schon nicht löschen kann).
lat. nihil.
http://it.wikipedia.org/wiki/Nulla" onclick="window.open(this.href);return false;
Wer's gerne kompliziert man, kann sich auch auf das französische "néant" berufen. http://fr.wikipedia.org/wiki/N%C3%A9ant" onclick="window.open(this.href);return false; was dann den Rahmen leicht sprengt.
Hoffe belustigt zu haben.
;-)

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: StringReplace mit Umlauten?

Beitrag von mse »

theo hat geschrieben:Nulla.
Hmm, nun interessiert mich natürlich brennend, was du nicht sagen wolltest. ;-)

Martin

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6873
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: StringReplace mit Umlauten?

Beitrag von af0815 »

enyaw_ecurb hat geschrieben:StrReplace ohne rfIgnoreCase (also AnsiReplaceStr) funktioniert...
StrReplace mit rfIgnoreCase (also AnsiReplaceText) haut nicht hin

Bug oder Feature? Leider brauche ich für meine Anwendung eigentlich letztere Variante...
Wäre schon einen Eintrag im Bugtracker wert, das das Verhalten zumindest dokumentiert ist.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: StringReplace mit Umlauten?

Beitrag von Hitman »

Bin mir nicht sicher, dass das ein Bug ist. AnsiStringReplace nimmt nunmal explizit "Ansi" (und eben nicht UTF8). Lazarus' Code Editor wird aber mit hoher Wahrscheinlichkeit die Dateien UTF8 kodieren. Du wirst also schon die Datei nach latin1 oder ähnliches umsetzen müssen, dass AnsiStringReplace auch so funktioniert wie du willst. Und dann nützt dir das immernoch nicht viel mit den GUI Elementen deiner eigenen Anwendung, weil die soweit ich weiß inzwischen auch alle UTF8 sprechen.
Welche FPC Version nimmt du überhaupt? Sowas könnte nämlich auch gut und gern in Trunk oder Fixes_2_2 behoben sein.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: StringReplace mit Umlauten?

Beitrag von theo »

mse hat geschrieben:Hmm, nun interessiert mich natürlich brennend, was du nicht sagen wolltest. ;-)
af0815 hat geschrieben:Wäre schon einen Eintrag im Bugtracker wert, das das Verhalten zumindest dokumentiert ist.
Naja, ANSIReplaceText behauptet ja nicht, es könne mit Unicode umgehen.
Da hilft auch Monta's Liebesmüh mit UTF8Decode nichts, das gäbe nämlich einen WideString zurück den AnsiReplaceText nicht entgegen nimmt.
Die Case-Insensitivität bei Unicode ist schwieriger als man denkt, und lässt sich eigentlich nur Locale spezifisch korrekt lösen.
Warum? Siehe z.B. hier http://www.i18nguy.com/unicode/turkish-i18n.html" onclick="window.open(this.href);return false;

Wenn du wirklich nur sowas
AnsiReplaceText('abcdßabcdßabcd', 'a', 'x')
machen willst, können dir evtl die utf8-tools behilflich sein: http://wiki.lazarus.freepascal.org/Theodp" onclick="window.open(this.href);return false;

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: StringReplace mit Umlauten?

Beitrag von Euklid »

theo hat geschrieben: Immerhin eine Gelegenheit ein paar Brocken italienisch [...] französische "néant" [...]
hmmm... habe mich schon immer gefragt, aus welchem Teil der Schweiz du wirklich stammst ;)

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: StringReplace mit Umlauten?

Beitrag von theo »

Euklid hat geschrieben: hmmm... habe mich schon immer gefragt, aus welchem Teil der Schweiz du wirklich stammst ;)
Ich auch ;-)

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: StringReplace mit Umlauten?

Beitrag von Scotty »

theo hat geschrieben:Da hilft auch Monta's Liebesmüh mit UTF8Decode nichts, das gäbe nämlich einen WideString zurück den AnsiReplaceText nicht entgegen nimmt.
Allerdings kann man den WideString dann schön "per Hand" durchsuchen und ersetzen.
BTW: Kann es sein, dass verschiedene FPC-Versionen Strings unterschiedliche handhaben? Unter Linux (2.3.1) kann ich problemlos s:WideString; s:=Edit1.Text; bearbeiten, unter Windows (2.2.4) muss ich alles explizit nach der Monta-Methode konvertieren. Ergo: Obacht!

enyaw_ecurb
Beiträge: 8
Registriert: Mi 4. Feb 2009, 00:21

Re: StringReplace mit Umlauten?

Beitrag von enyaw_ecurb »

Ich habe grade nochmal fpc und lazarus mit svn auf den neusten Stand gebracht. Am Verhalten hat sich nichts geändert.

@monta: Mit utf8Decode tut sich da leider auch nichts. Problem besteht.

@theo: AnsiReplaceText soll natürlich mit ansi funktionieren, klar ;-) Intern benutzt das aber auch nur ein StringReplace. Und wenn man sich die StringReplace-Funktion anschaut wird dort intern wieder ein AnsiUpperCase verwendet. In der Beschreibung von AnsiUpperCase (http://www.freepascal.org/docs-html/rtl ... rcase.html) steht nun explizit "It takes into account the operating system language settings when doing this, so special characters are converted correctly as well.". Dazu soll ein Widestring-Manager installiert sein, was ich hoffentlich mit Einbinden von cwstring getan habe.
Meine Frage: Wenn eine Ansi-Funktion jetzt vorgibt mit speziellen Zeichen zurechtzukommen und dafür einen widestringmanager braucht, dann sollte die Sache doch eigentlich funktionieren, oder? Immerhin klappt es mit normalen Umlauten 'ä,ö,ü' auch ganz gut...

Ganz ehrlich blick ich bei den ganzen Kodierungen nicht mehr durch. Ich hab schon versucht das ganze explizit über den widestringmanager von utf8 nach unicode und dann von unicode wieder in ansi zu konvertieren. Problem besteht...

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: StringReplace mit Umlauten?

Beitrag von theo »

enyaw_ecurb hat geschrieben: Meine Frage: Wenn eine Ansi-Funktion jetzt vorgibt mit speziellen Zeichen zurechtzukommen und dafür einen widestringmanager braucht, dann sollte die Sache doch eigentlich funktionieren, oder? Immerhin klappt es mit normalen Umlauten 'ä,ö,ü' auch ganz gut...
Es ist eher seltsam, dass es mit den Umlauten klappt.

Vergiss das Ansi Zeug.
Hier gibt's eine Fkt. die scheint zu funzen http://www.delphipraxis.net/post377911.html#377911" onclick="window.open(this.href);return false;

Einfach die Params/das Resultat von/nach UTF-8 wandeln.

Aber das ist nur gut für den "Hausgebrauch". Wenn du das seriös machen willst, musst du mindestens noch normalisieren.
Memo1.Text:= TCharacter.Normalize_NFKC(Memo1.text); ( http://wiki.lazarus.freepascal.org/Theodp" onclick="window.open(this.href);return false; )


EDIT: Nö, Sorry der Code im Link oben ist gar nicht case-insensitive (Wie da geschrieben steht).
Für den Hausgebrauch kann man aber den Code aus "sysstr.inc" rauskopieren und auf WideString anpassen.
Das müsste gehen.

Code: Alles auswählen

Function WideStringReplace(const S, OldPattern, NewPattern: WideString;  Flags: TReplaceFlags): WideString;
var
  Srch,OldP,RemS: WideString; // Srch and Oldp can contain uppercase versions of S,OldPattern
  P : Integer;
begin
  Srch:=S;
  OldP:=OldPattern;
  if rfIgnoreCase in Flags then
    begin
    Srch:=WideUpperCase(Srch);
    OldP:=WideUpperCase(OldP);
    end;
  RemS:=S;
  Result:='';
  while (Length(Srch)<>0) do
    begin
    P:=Pos(OldP, Srch);
    if P=0 then
      begin
      Result:=Result+RemS;
      Srch:='';
      end
    else
      begin
      Result:=Result+Copy(RemS,1,P-1)+NewPattern;
      P:=P+Length(OldP);
      RemS:=Copy(RemS,P,Length(RemS)-P+1);
      if not (rfReplaceAll in Flags) then
        begin
        Result:=Result+RemS;
        Srch:='';
        end
      else
         Srch:=Copy(Srch,P,Length(Srch)-P+1);
      end;
    end;
end;

enyaw_ecurb
Beiträge: 8
Registriert: Mi 4. Feb 2009, 00:21

Re: StringReplace mit Umlauten?

Beitrag von enyaw_ecurb »

Hey, cool! Das scheint zu funktionieren, danke!

Ich hätte jetzt umständlich was für widestrings selbst geschrieben... So ist natürlich viel einfacher ;-) Falls es noch Probleme mit alt-ägyptisch oder Keilschrift geben sollte - kann ich nicht testen, brauch ich nicht.

Jetzt aber mal ehrlich: Es wäre eigentlich schon elementar, dass man ein funktionierendes StringReplace (für widestrings) in der RTL hätte...

Antworten