Kind mit Maske (verzweifelter Star Wars Fan): String in 180 Zeichen aufteilen und in Array packen. (Spezialfall Wörter)

Hallo,

ich habe einen Frage, ich habe einen String (Text) und möchte Ihn aufteilen (in ein Array, jeder Teil max. 180 Zeichen).

Bsp.:

$string_anfang = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

$array_ziel = array("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam","et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing"....);

Mein Problem ist nun, das ich zwar schön mit substr den Text schneiden kann, leider zerschneide ich so auch Wörter. Gibt es hierfür eine Lösung?

    1. Hello,

      Gefunden: http://de.php.net/manual/de/function.wordwrap.php

      Genau. Das war der erste Denkschritt!
      Der zweite sollte sein, für welche Kodierung die Funktion funktionieren soll:

      • Singlebyte oder
      • Multibyte
      • ...

      Liebe Grüße
      Tom S.

      --
      Es gibt nichts Gutes, außer man tut es!
      Das Leben selbst ist der Sinn.
      1. @@TS

        Genau. Das war der erste Denkschritt!
        Der zweite sollte sein, für welche Kodierung die Funktion funktionieren soll:

        • Singlebyte oder
        • Multibyte
        • ...

        Wenn die Antwort darauf „Singlebyte“ sein sollte, hat man im nullten Denkschritt schon was falsch gemacht.

        LLAP 🖖

        --
        “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
        1. Hello,

          Genau. Das war der erste Denkschritt!
          Der zweite sollte sein, für welche Kodierung die Funktion funktionieren soll:

          • Singlebyte oder
          • Multibyte
          • ...

          Wenn die Antwort darauf „Singlebyte“ sein sollte, hat man im nullten Denkschritt schon was falsch gemacht.

          Wie herum Du das sortierst, ist mir schnulli.

          Wichtig ist mMn nur, dass man an die Kodierung denkt und nicht "Stringfunktion" stumpf als "Zeichenkettenfunktion" übersetzt.

          Frohe Festtage

          Nikomaus mit Geschenkesack

          und liebe Grüße
          Tom S.

          --
          Es gibt nichts Gutes, außer man tut es!
          Das Leben selbst ist der Sinn.
          1. @@TS

            Wichtig ist mMn nur, dass man an die Kodierung denkt und nicht "Stringfunktion" stumpf als "Zeichenkettenfunktion" übersetzt.

            Ich würde schon string „stumpf“ mit Kette übersetzen, Zeichenkette in dem Fall.

            Das Problem ist nicht die Übersetzung, sondern PHP: das werden Funktionen als Stringfunktionen bezeichnet, die überhaupt nicht auf Zeichenketten operieren (sondern auf Bytesequenzen).

            LLAP 🖖

            --
            “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
            1. Tach!

              Das Problem ist nicht die Übersetzung, sondern PHP: das werden Funktionen als Stringfunktionen bezeichnet, die überhaupt nicht auf Zeichenketten operieren (sondern auf Bytesequenzen).

              Welche konreten Auswirkungen kann das beim Anwenden dieser Funktion haben?

              dedlfix.

              1. Hallo dedlfix,

                wenn dein PHP Script mit Unicode-Strings operieren können soll, ist die Auswirkung, dass Unicode-Bytesequenzen meuchlings zerhäckselt werden können.

                Bei den mb-Funktionen von PHP passiert das nicht. Leider gibt's kein mb_wordwrap, das müsste man programmieren. Hier gibt's ein paar Versuche dazu.

                Rolf

                --
                sumpsi - posui - clusi
                1. Tach!

                  Welche konreten Auswirkungen kann das beim Anwenden dieser Funktion haben? wenn dein PHP Script mit Unicode-Strings operieren können soll, ist die Auswirkung, dass Unicode-Bytesequenzen meuchlings zerhäckselt werden können.

                  Das ist mir noch zu unkonkret. Unter welchen genauen Umständen passiert das?

                  dedlfix.

                  1. Hallo dedlfix,

                    mal angenommen, ich würde mit einem UTF-8 kodierten PHP Script arbeiten und darin schreiben:

                    echo wordwrap("Der Bär im Klärwerk trübt die Brühe", 20)."\n";
                    echo wordwrap("Der Bar im Klarwerk trübt die Brühe", 20)."\n";
                    
                    echo substr("Ein Bär", 0, 6)."\n";
                    echo mb_substr("Ein Bär", 0, 6)."\n";
                    

                    Fehler 1 ist, dass wordwrap im 1. Aufruf "Klärwerk" auf die 2. Zeile schiebt, obwohl es in Zeile 1 gepasst hätte. Das sieht man im 2. Aufruf, da ist "Klarwerk" auf Zeile 1 geblieben. Es zählt also falsch.

                    Der 3. echo gibt "Ein B\xc3" aus statt "Ein Bä", weil dem ä (UTF-8 \xC3A4) die Hälfte abgeschnitten wird. Im 4. echo passiert das nicht.

                    So. Und auf welchem Glatteis bin ich jetzt, nachdem Du mich so schön geführt hast?

                    Rolf

                    --
                    sumpsi - posui - clusi
                    1. Tach!

                      mal angenommen, ich würde mit einem UTF-8 kodierten PHP Script arbeiten und darin schreiben:

                      echo wordwrap("Der Bär im Klärwerk trübt die Brühe", 20)."\n";
                      echo wordwrap("Der Bar im Klarwerk trübt die Brühe", 20)."\n";
                      
                      echo substr("Ein Bär", 0, 6)."\n";
                      echo mb_substr("Ein Bär", 0, 6)."\n";
                      

                      Fehler 1 ist, dass wordwrap im 1. Aufruf "Klärwerk" auf die 2. Zeile schiebt, obwohl es in Zeile 1 gepasst hätte.

                      Gut, kann man als Fehler ansehen. Das Ergebnis ist jedoch nur eine nicht optimale Nutzung des Platzes, aber kein K.O.-Kriterium.

                      Der 3. echo gibt "Ein B\xc3" aus statt "Ein Bä", weil dem ä (UTF-8 \xC3A4) die Hälfte abgeschnitten wird. Im 4. echo passiert das nicht.

                      Diese beiden Fälle sind zwar richtig, aber hier irrelevant. Jedenfalls nicht in dieser Form. Dazu .. siehe nächsten Abschnitt.

                      So. Und auf welchem Glatteis bin ich jetzt, nachdem Du mich so schön geführt hast?

                      Das Abschneiden überlanger Wörter war eher der Fall, an dem ich ein potentielles Problem gesehen habe. Aber auch nur dann, wenn man den Parameter $cut auf true setzt. Hat man das nicht, tritt kein Zerstückeln innerhalb von Bytesequenzen auf. Und da Wörter mit 180 Zeichen kaum verbreitet sind, wird $cut wohl auf false bleiben und keine derartigen Probleme verursachen. Das sehe ich jetzt also auch nicht aus Ausschlusskriterium an.

                      Bleibt lediglich ein Schönheitsfehler. Und wie wahrscheinlich ist, dass der deutlich auffällt? Kommt auf die Sprache des zu verarbeitenden Textes an und die Häufigkeit von Nicht-ASCII-Buchstaben in Wörtern.

                      dedlfix.

                      1. Hallo dedlfix,

                        du wirst sicher recht haben. In unserem Sprachraum, der sich größtenteils mit Basic Latin bedienen lässt, wird das kein Problem sein. Im osteuropäischen Raum kommt allerdings schon recht viel Latin Extended A/B hinzu, und danach wird's teuer. Da wir hier in einem deutschsprachigen Forum sind, ist der Use-Case unwahrscheinlich.

                        Aber Gunnar betrachtet ja gerne ein paar Use Cases mehr 😂

                        Rolf

                        --
                        sumpsi - posui - clusi
                        1. Tach!

                          Aber Gunnar betrachtet ja gerne ein paar Use Cases mehr 😂

                          Das ist ja auch nicht grundsätzlich verkehrt. Am Ende muss man aber Aufwand und Nutzen im Verhältnis betrachten. Der Aufruf einer vorhandenen Funktion ist so gut wie kein Aufwand. Eine UTF-8-taugliche Lösung zu finden, deren Qualität zu beurteilen oder gar selbst eine zu entwickeln, ist deutlich mehr Aufwand, der sich vielleicht nicht rentiert. Sollte sich später herausstellen, dass die nicht-UTF-8-taugliche Funktion doch zu viele Nachteile mitbringt, dann kommt hat man immer noch denselben Aufwand, weil der von der Vergangenheit vernachlässigbar war.

                          Zur Entscheidungsfindung kommen auch noch Kriterien hinzu, die man als Außenstehender eventuell benennen aber nicht unbedingt beantworten kann. Zum Beispiel, wie wichtig es ist, dass die Lösung absolut zuverlässig arbeitet

                          dedlfix.

                        2. @@Rolf B

                          du wirst sicher recht haben. In unserem Sprachraum, der sich größtenteils mit Basic Latin bedienen lässt, wird das kein Problem sein. Im osteuropäischen Raum kommt allerdings schon recht viel Latin Extended A/B hinzu, und danach wird's teuer. Da wir hier in einem deutschsprachigen Forum sind, ist der Use-Case unwahrscheinlich.

                          Aber Gunnar betrachtet ja gerne ein paar Use Cases mehr 😂

                          Что ты говоришь?

                          LLAP 🖖

                          --
                          “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
                2. hi Rolf,

                  wenn Silbentrennung nicht erforderlich ist, reicht es doch, den Text am Leerzeichen zu splitten (explode). Das Ergebnis ist ein Array mit Wörtern und da geht auch bei einer UTF-8-Kodierung nichts kaputt.

                  $satz = "Ein Bär, im Wald lebend, verfügt über ein Vermögen von 2.5 €.";
                  $words = explode(" ", $satz);
                  

                  Für die Ausgabe kann dann beliebig gruppiert werden. MfG

                  1. @@pl

                    wenn Silbentrennung nicht erforderlich ist, reicht es doch, den Text am Leerzeichen zu splitten (explode). Das Ergebnis ist ein Array mit Wörtern und da geht auch bei einer UTF-8-Kodierung nichts kaputt.

                    $satz = "Ein Bär, im Wald lebend, verfügt über ein Vermögen von 2.5 €.";
                    $words = explode(" ", $satz);
                    

                    Doch, da geht was kaputt – zwischen 2.5 und €.. An der Stelle darf nicht getrennt werden; da gehört ein geschütztes Leerzeichen U+00A0 NBSP dazwischen. Gerne auch ein schmales U+202F NNBSP.

                    LLAP 🖖

                    --
                    “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
                    1. @@pl

                      wenn Silbentrennung nicht erforderlich ist, reicht es doch, den Text am Leerzeichen zu splitten (explode). Das Ergebnis ist ein Array mit Wörtern und da geht auch bei einer UTF-8-Kodierung nichts kaputt.

                      $satz = "Ein Bär, im Wald lebend, verfügt über ein Vermögen von 2.5 €.";
                      $words = explode(" ", $satz);
                      

                      Doch, da geht was kaputt – zwischen 2.5 und €.. An der Stelle darf nicht getrennt werden; da gehört ein geschütztes Leerzeichen U+00A0 NBSP dazwischen. Gerne auch ein schmales U+202F NNBSP.

                      Das ist dann wohl auch eine Anforderung an den Autor. explode() jedenfalls splittet an den Zeichen die der Programierer dafür vorsieht, oder hast Du da andere Erfahrungen gemacht?

                      MfG

                      1. @@pl

                        Doch, da geht was kaputt – zwischen 2.5 und €.. An der Stelle darf nicht getrennt werden; da gehört ein geschütztes Leerzeichen U+00A0 NBSP dazwischen. Gerne auch ein schmales U+202F NNBSP.

                        Das ist dann wohl auch eine Anforderung an den Autor.

                        Schön wär’s. Nur dass Autoren oftmals keine Ahnung haben, was ein geschütztes Leerzeichen ist – geschweige denn, wie man das eingibt.

                        Insofern ist es eine Anforderung an den Programierer, Leerzeichen zwischen Zahl und Eurozeichen (bzw. anderen Einheitenkürzeln) durch (schmale) geschützte Leerzeichen zu ersetzen.

                        LLAP 🖖

                        --
                        “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
                        1. Hi,

                          Doch, da geht was kaputt – zwischen 2.5 und €.. An der Stelle darf nicht getrennt werden; da gehört ein geschütztes Leerzeichen U+00A0 NBSP dazwischen. Gerne auch ein schmales U+202F NNBSP.

                          Das ist dann wohl auch eine Anforderung an den Autor.

                          Schön wär’s. Nur dass Autoren oftmals keine Ahnung haben, was ein geschütztes Leerzeichen ist – geschweige denn, wie man das eingibt.

                          Das ist interessant. Denn wie diese "Zeichen" einzugeben sind weiß ich nämlich auch nicht, auf meiner Tastatur jedenfalls sind die gar nicht drauf.

                          Insofern ist es eine Anforderung an den Programierer, Leerzeichen zwischen Zahl und Eurozeichen (bzw. anderen Einheitenkürzeln) durch (schmale) geschützte Leerzeichen zu ersetzen.

                          Programmertechnisch sind non breaking und thin space problemlos zu erzeugen, das geht sogar mit PHP. Bleibt die Frage nach dem Algorithmus womit ein Programm erkennen kann wo diese Ersetzungen vorzunehmen sind. Also bspw. woran erkennt, daß es sich in einem laufenden Text um eine Folge von Zahl und Maßeinheit resp. Kürzel handelt. Ich denke, ohne Zuarbeit des Autors ist das gar nicht vollumfänglich möglich.

                          Oder gibt es eine PHP Funktion die das kann? MfG

                          1. @@pl

                            Das ist interessant. Denn wie diese "Zeichen" einzugeben sind weiß ich nämlich auch nicht, auf meiner Tastatur jedenfalls sind die gar nicht drauf.

                            Auf dem Mac ergibt [alt][space] U+00A0 NBSP. Unter Windows ist das AFAIR ähnlich.

                            Bleibt die Frage nach dem Algorithmus womit ein Programm erkennen kann wo diese Ersetzungen vorzunehmen sind. Also bspw. woran erkennt, daß es sich in einem laufenden Text um eine Folge von Zahl und Maßeinheit resp. Kürzel handelt.

                            Nach \d € kann man schon suchen. Bzw. auch Striche '-', '‒', '–', '—' mit einbeziehen. Für die Einheitenkürzel müsste man sich natürlich eine Liste erstellen, was man da alles nehmen will.

                            LLAP 🖖

                            --
                            “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
                3. Hello,

                  wenn dein PHP Script mit Unicode-Strings operieren können soll, ist die Auswirkung, dass Unicode-Bytesequenzen meuchlings zerhäckselt werden können.

                  Bei den mb-Funktionen von PHP passiert das nicht. Leider gibt's kein mb_wordwrap, das müsste man programmieren. Hier gibt's ein paar Versuche dazu.

                  Und in meinem Post auch.

                  Das ist aber nur dann relevant, wenn die "Zeilenlänge" in Bytes relevant ist, wie z. B. bei der eMail-Übertragung empfohlen.

                  Wenn man lediglich nach jedem Wort eine Trennung durchführen will, egal wie lang die Abschnitte dann in Bytes werden, kann man das auch mittels der üblichen Single-Byte-"String"-funktionen. Man muss nur die als Trennzeichen gewünschten Zeichen identifizieren. Ob man dafür Single-Byte-Funktionen oder Multi-Byte-Funktionen benötigt, sollte ausschließlich von den verwendeten Trennzeichen abhängen.

                  Da die Texte aber heute üblicherweise in UTF-8 kodiert vorliegen, wird man das voraussichtlich berücksichtigen müssen.

                  Liebe Grüße
                  Tom S.

                  --
                  Es gibt nichts Gutes, außer man tut es!
                  Das Leben selbst ist der Sinn.
  1. Hello,

    Mein Problem ist nun, das ich zwar schön mit substr den Text schneiden kann, leider zerschneide ich so auch Wörter. Gibt es hierfür eine Lösung?

    Und wenn Du nicht die passende "String"-funktion benutzt, dann zerschneidest Du auch Zeichen damit.

    Hier zur Diskussion eine Funktion, die dir vielleicht schon mal einen Schritt weiter helfen könnte:

    # Umbrüche steuern bei Multibyte-Kodierung
    
    	<?php
    	function utf8_wordwrap($string, $width=75, $break="\n", $cut=false)
    	{
    	  if($cut) {
    		// Match anything 1 to $width chars long followed by whitespace or EOS,
    		// otherwise match anything $width chars long
    		$search = '/(.{1,'.$width.'})(?:\s|$)|(.{'.$width.'})/uS';
    		$replace = '$1$2'.$break;
    	  } else {
    		// Anchor the beginning of the pattern with a lookahead
    		// to avoid crazy backtracking when words are longer than $width
    		$pattern = '/(?=\s)(.{1,'.$width.'})(?:\s|$)/uS';
    		$replace = '$1'.$break;
    	  }
    	  return preg_replace($search, $replace, $string);
    	}
    
    
    #	Und selbstverständlich nicht vergessen, preg_quote zu benutzen für die $width und $break Parameter, wenn sie von außen kommen.  
    
    ?>
    

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.