RegExp: \b matcht auch Umlaute?
Andreas Dölling
- php
Hallo,
ist es richtig, daß \b auch Umlaute als Wortgrenze macht?
Wenn ja: was kann man dagegen tun?
Ich habe in einem Text (UTF-8) das Wort "Geräte". Den Text will ich in zwei Hälften teilen.
Dazu verwende ich diesen Ausdruck:
preg_match("/^(.{0,".(strlen($contents)/2+20)."})(?:\b)(.*)$/sm", $contents, $matches);
Das klappt auch ganz wunderbar - $matches[1] enthält die erste Hälfte, $matches[2] die zweite, wobei normalerweise kein Wort zerschnitten wird.
Bei dem Text mit dem Wort "Geräte" allerdings steht dieses Wort am Ende der ersten Hälfte und wird nach dem "ä" abgeschnitten, anstatt daß das tatsächliche Wortende oder das Ende des vorhergehenden Wortes benutzt wird.
Hattet Ihr mit diesem Problem schon zu tun? Wie habt Ihr es gelöst?
Thanx und ciao,
Andreas
Hallo,
ersetze ich in dem besagten Text die "ä" durch "a", dann klappt es - das Wort "Gerate" wird nicht geteilt.
Quod erat demonstrandum.
Wie also umgehen mit diesem Problem?
Ciao,
Andreas
Hallo Andreas,
ersetze ich in dem besagten Text die "ä" durch "a", dann klappt es - das Wort "Gerate" wird nicht geteilt.
Quod erat demonstrandum.Wie also umgehen mit diesem Problem?
Es gibt einen Modifikator '/u' für UTF-8-Patterns.
Und wenn ich Zeichenklassen mit _allen_ definierten Buchstaben brauche, benutze ich '[:alpha:]' und nicht 'a-zA-Z' oder '\w'. Möglicherweise kann ja '/[[1]]/' dein '\b' ersetzen ...
MffG
EisFuX
:alpha: ↩︎
Hallo,
danke für den Tipp!
Leider ändert sich aber auch mit setlocale(LC_ALL, 'de_DE'); oder mit setlocale(LC_TIME, 'de_DE.UTF8'); nichts am Verhalten meines Scripts.
:/
Ciao,
Andreas
你好 Andreas,
Leider ändert sich aber auch mit setlocale(LC_ALL, 'de_DE'); oder mit setlocale(LC_TIME, 'de_DE.UTF8'); nichts am Verhalten meines Scripts.
:/
ich glaube, setlocale(LC_ALL,"de_DE.UTF8") wäre auch sinnvoller :) Vorrausgesetzt, das Locale existiert, das musst du natürlich vorher nachprüfen.
再见,
克里斯蒂安
gudn tach!
ist es richtig, daß \b auch Umlaute als Wortgrenze macht?
Wenn ja: was kann man dagegen tun?
evtl. waere eine moeglichkeit setlocale.
eine andere moeglichkeit: \b und \w nachbauen...
"A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively." (aus dem php-manual ueber pcre)
Ich habe in einem Text (UTF-8)
dann wird dir evtl. das weiterhelfen.
(?:\b)
ist uebrigens das gleiche wie
\b
Hattet Ihr mit diesem Problem schon zu tun?
noe, ich vermeide umlaute und sz bzw. ersetze sie.
prost
seth
Hallo,
eine andere moeglichkeit: \b und \w nachbauen...
ungern...
"A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively." (aus dem php-manual ueber pcre)
Ja, hast recht - aus dieser Definition geht klar hervor, daß \b abhängig von der locale-Einstellung ist.
dann wird dir evtl. das weiterhelfen.
Phew - damit habe ja noch nie gearbeitet.
noe, ich vermeide umlaute und sz bzw. ersetze sie.
Hm, genau _das_ will ich aber nicht mehr. Ich bin gerade dabei, das Textarchiv eines Fanzines zu "säubern", wo im Moment alle Texte als HTML mit Umlaut-Entities und ziemlich verschwurbeltem Old-School-Markup vorliegen.
Und ein Ziel ist es auch, die Texte als saubere UTF-8-Texte vorliegen zu haben - ohne Entities, mit ganz normalen Umlauten.
prost
Erst heute abend!
;)
Ciao,
Andreas
Hallo,
ich habe nun doch Seths Vorschlag aufgegriffen, mir \b selbst zusammenzusetzen. War dann doch nicht so problematisch (im Gegensatz zur Definition von \w).
Mein regulärer Ausdruck sieht nun so aus:
/^(.{0,".(strlen($contents)/2+20)."})\s,.!?-$/sm
Und damit klappt es.
Seht Ihr noch Schwachstellen?
Danke auf jeden Fall für die superschnelle Hilfe!
Ciao,
Andreas
Hallo,
/^(.{0,".(strlen($contents)/2+20)."})\s,.!?-$/sm
da es auch ungerade Zahlen gibt, sollte es dann doch besser so aussehen:
/^(.{0,".(ceil(strlen($contents)/2)+20)."})\s,.!?-$/sm
;)
Ciao,
Andreas
gudn tach!
/^(.{0,".(ceil(strlen($contents)/2)+20)."})\s,.!?-$/sm
das ist aber nicht mehr das gleiche vie vorher, denn vorher wurde das worttrennzeichen in $1 oder $2 (je nach laenge von $contents und der position des trennzeichens) gespeichert. jetzt geht es floeten.
btw.: je nach beschaffenheit des strings und den informationen, die dir darueber vorliegen, kann es besser sein die zeichenklasse der trennzeichen als negierte nicht-trennzeichen-klasse zu betrachten. also statt [\s,.!?-] [^a-zA-Z0-9_äöüÄÖÜß].
eine etwas mehr an \b angelehnte nachbau-idee ist uebrigens folgende:
$z='[a-zA-Z0-9_äöüÄÖÜß]';
$n='[^a-zA-Z0-9_äöüÄÖÜß]';
(?:(?<!$z)(?!$n)|(?<!$n)(?!$z))
spontan faellt mir kein beispiel ein, bei welchem \b und dieses ding was unterschiedliches machen wuerden (mal von von den locale-einstellungen abgesehen).
prost
seth