Andreas Dölling: RegExp: \b matcht auch Umlaute?

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

-- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
  1. 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

    -- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
    1. 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 '/[^[:alpha:]]/' dein '\b' ersetzen ...

      MffG
      EisFuX

      -- Auch meine Hosenträger sind intelligent, in dem Sinne, das man sie regulieren kann. Sie besitzen ein adaptives Verhalten.
      Stanisław Lem
  2. 你好 Andreas,

    worauf \b matcht, hängt vom Locale ab.

    再见,
     克里斯蒂安

    --
    Frühling | Programmierer auf Crack
    Das Sein entsteht aus dem Nicht-Sein.

    http://wwwtech.de/

    1. 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

      -- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
      1. 你好 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.

        再见,
         克里斯蒂安

        --
        Frühling | Programmierer auf Crack
        Kommt ein Vektor zur Drogenberatung: "Hilfe, ich bin linear abhaengig!"

        http://wwwtech.de/

  3. gudn tach!

    ist es richtig, daß \b auch Umlaute als Wortgrenze macht?

    u.u.

    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

    1. 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

      -- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
  4. 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

    -- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
    1. 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

      -- "Das Corporate Design für das Internet sieht eine Reihe von Grafikelementen vor, die die Optik der Webseite visuell und funktionell beeinflussen." - (Zitat aus dem "Styleguide Corporate Design"  eines großen Konzerns...)
      1. 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