Reguläre Ausdrücke suchen / ersetzen - und das deutsche SZ
Nick
- javascript
0 Alexander (HH)0 Nick0 molily
0 Alexander (HH)0 molily
0 Don P0 Don P
Hallo,
ich suche in einem Text mittels eines Regulären Ausdrucks nach allen alleinstehenden Wörtern "er" und ersetze diese jeweils über 'replace' durch ein "sie".
----------------------------------------------------
reg = /\ber\b/; = "er" jeweils mit Wortgrenze - also alleine stehend.
wert = mein zu durchsuchender Text;
while (reg.test(wert))
wert = wert.replace(reg,'sie');
----------------------------------------------------
Kein Problem - bis auf den Sonderfall "großer" - daraus wird in diesem Fall nämlich "großsie". SCHEI ....
Gegenprobe: das Wort "grosser" bleibt unverändert !
Fazit: das "ß" wird nicht als Teil eines Wortes erkannt, sondern als Wortgrenze interpretiert.
Auch das Ersetzen des "ß" durch das entsprechende "benannte Zeichen" ( ß) ändert nichts daran .... !
Tricks ? Tipps ? Jede wette, hier gibt es eine Lösung ! Bloß welche ?!
Mit Dank im Voraus Nick
Moin Moin!
Erkläre der RE-Engine, dass Du deutsche Texte bearbeiten willst, und dass daher auch die Umlaute und das ß als normale Buchstaben gewertet werden sollen.
Das fällt unter den Begriff "localization" (L10N). Ob und wie weit Browser damit was anfangen können, weiß ich nicht. Ich würde im ersten Schritt mal den Browser und ggf. das OS auf Deutsch umstellen und die HTML-Seite explizit als Deutsch deklarieren (<html lang="de">).
Alexander
Moin von HH nach HH.
Dokumentenkopf und Computer - alles typisch DEUTSCH.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1" />
Mfg Nick
Moin Moin!
Dokumentenkopf und Computer - alles typisch DEUTSCH.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1" />
Soweit Plan A.
Plan B: Doku lesen. Für den Mozilla ist \w exakt equivalent zu [a-zA-Z0-9_], egal was hinsichtlich Sprachen passiert (1, 2), \W das exakte Gegenteil [^a-zA-Z0-9_], und \b, der Übergang zwischen \w und \W, ist daher auch immer gleich.
Offensichtlich ist noch niemandem aufgefallen, dass diese Definition von \w für nicht-englische Sprachen nicht sonderlich sinnvoll ist. Perl ist da schon ein ganzes Stück weiter.
Du mußt Dir also \w, \W und \b selbst aus Character-Klassen zusammenstricken.
Alexander
Moltid.
"Du mußt Dir also \w, \W und \b selbst aus Character-Klassen zusammenstricken."
Nix verstehen ... !
"Du mußt Dir also \w, \W und \b selbst aus Character-Klassen zusammenstricken."
Nix verstehen ... !
\b ist nichts anderes als die Zeichenklasse [^a-zA-Z0-9_]. D.h. »irgendein Zeichen, dass nicht ein lateinischer Buchstabe, eine arabische Ziffer oder der Unterstrich ist«.
Wie du gemerkt hast, sind die Millionen restlichen Schriftzeichen der Welt da ausgenommen, insofern ist \b nicht wirklich für natürlichsprachige Texte brauchbar.
Jetzt könntest du dir also eine genauere Zeichenklasse definieren, die zumindest die in deinem Text verwendeten Zeichen einschließt:
"Er, er ist groß, größer, ein noch größerer".match(/[^a-zA-ZüöäÜÖÄß]er[^a-zA-ZüöäÜÖÄß]/i)
Ergebnis: [ " er " ]
Um das erste und letzte freistehende »er« zu finden, müsstest du noch schreiben:
"Er war ein großer Verehrer, er war ein noch größerer Versager. er".replace(/(^|[^a-zA-ZüöäÜÖÄß])er($|[^a-zA-ZüöäÜÖÄß])/gi, "$1sie$2")
Ergebnis: "sie war ein großer Verehrer, sie war ein noch größerer Versager. sie"
Groß- und Kleinschreibung beibehalten wäre komplizierter, da müsste man vermutlich mit einer Ersetzungsfunktion arbeiten.
Mathias
Erkläre der RE-Engine, dass Du deutsche Texte bearbeiten willst, und dass daher auch die Umlaute und das ß als normale Buchstaben gewertet werden sollen.
Die JS-Engine versteht immer dasselbe unter \b, weil das in ECMAScript so festgelegt ist; eine Lokalisation gibts da nicht.
Mathias
Moin Moin!
Die JS-Engine versteht immer dasselbe unter \b, weil das in ECMAScript so festgelegt ist; eine Lokalisation gibts da nicht.
Wie kann man nur so vernagelt sein? Naja, es bleibt ja noch die Hoffnung, dass irgendwann mal jemand die Spec verbessert.
Möglichkeiten gäbe es ja einige, z.B. nutzt die Definition nur drei Flags (g, i und m), Mozilla fügt noch y (sticky) hinzu. Da bleibt noch genügend Luft für ein Flag, das \b, \w und \W auf die (irgendwie) ausgewählte Sprache erweitert.
Die größere Frage ist da eher, wie man die Sprache auswählt. <html lang="de"> wäre ein Weg, aber niemand hintert mich, mehrere Sprachen in einem Dokument zu verwenden, z.B. mit <div lang="fr">. Wenn Javascript dann aus verschiedenen Dokumentteilen Strings extrahiert, muß die RE-Engine jeweils anhand der String-Herkunft entscheiden, welche Sprache gerade zur Anwendung kommt. Die String-Objekte müßten also um ein Attribut erweitert werden, dass die Sprache (für die RE-Engine) enthält.
Richtig übel wird das Modell allerdings, wenn jemand Strings aus verschiedenen Sprachen aneinander hängt und die RE-Engine darauf ansetzt. Welche Sprache ist dann zu verwenden?
Die Frage kann Perl auch nicht beantworten, dort wird die Locale global gesetzt, die per Locale ausgewählte Sprache gilt dann für alle REs und alle Strings. Das Modell wäre in Javascript auch recht einfach: document.setLocate("de-DE"), dann matcht /\w/ auch Umlaute und ß.
Alexander
Die größere Frage ist da eher, wie man die Sprache auswählt. <html lang="de"> wäre ein Weg
ECMAScript hat mit HTML nichts zu tun, also wird ECMAScript seine Sprachwahl nicht von HTML abhängig machen.
Die Frage kann Perl auch nicht beantworten, dort wird die Locale global gesetzt, die per Locale ausgewählte Sprache gilt dann für alle REs und alle Strings. Das Modell wäre in Javascript auch recht einfach: document.setLocate("de-DE"), dann matcht /\w/ auch Umlaute und ß.
So würde es wohl auch in ECMAScript laufen, aber vermutlich eher als Methode des globalen Objektes oder als statische Methode von RegExp - weil document HTML- bzw. DOM-spezifisch ist, ECMAScript aber eine Sprache, die in verschiedenen Host-Umgebungen eingesetzt wird.
Mathias
Hallo,
Fazit: das "ß" wird nicht als Teil eines Wortes erkannt, sondern als Wortgrenze interpretiert.
Quick and dirty:
var
reg = /([^\Bß])er\b/,
wert='Kein großer Text, aber er ist zum Testen geeignet.'
;
while (reg.test(wert)) wert = wert.replace(reg,"$1"+'sie');
Gruß, Don P
Hallo,
Sorry das war zu dirty. Funktioniert doch nicht immer. :-((
Gruß, Don P