Knut: Wie behandelt PHP Whitespaces?

Hallo,

Ich bins nochmals mit einem weiteren "Problem"...

...und zwar verstehe ich nicht ganz, wie sich PHP bezüglich Whitespaces verhält.

Habe herumprobiert -

  • Szenario 1: eine ganz einfache PHP Ausgabe im DOM-Tree:
<?php
$eineVar = "   Viele      Leerzeichen ";
 echo $eineVar;
?>

...alle überschüssigen Leerzeichen scheinen in diesem Fall zu verschwinden.

  • Szenario 2: Habe ein ähnliches Szenario dann via fetch() in Kombination mit einer externen PHP-Datei probiert
const options = {
	method: "POST",
	body: "    Viele  Leerzeichen    "
};

const response = fetch("./testing_php_trim.php", options)
	.then(data => data.text())
	.then(text => console.log(text));

...und PHP-seitig (für Testzwecke) nur mal via file_get_contents zurückgeschickt (in der Anwendung dann wohl eher mit FormData):

// testing_php_trim.php
<?php
$content = trim(file_get_contents("php://input"));
echo $content;
echo "\n";
echo trim($content);
?>

...auch hier scheint ein automatisches trim() zu passieren, beide $contents werden clientseitig in der Konsole gleich ausgegeben.

Ich habe mich ein wenig damit gespielt, um ein Gefühl dafür zu bekommen, wie auf Whitespaces reagiert wird und hatte dann irgendwann eine Situation, wo die Whitespaces plötzlich ausgegeben wurden. Wie das Leben nun mal so spielt, dachte ich mir zu diesem Zeitpunkt nichts und überschrieb den Code, weswegen ich ihn hier leider nicht mehr reproduzieren kann :(

Bin aber nun ein wenig verunsichert.

Wie behandelt PHP Whitespaces genau und wann ist trim() notwendig?

Danke, Knut.

  1. @@Knut

    • Szenario 1: eine ganz einfache PHP Ausgabe im DOM-Tree:
    <?php
    $eineVar = "   Viele      Leerzeichen ";
     echo $eineVar;
    ?>
    

    ...alle überschüssigen Leerzeichen scheinen in diesem Fall zu verschwinden.

    Nein, nicht durch PHP. Das geschieht im Browser beim Parsen des generierten HTML.

    😷 LLAP

    --
    „Dann ist ja auch schrecklich, dass wir in einem Land leben, in dem nicht nur Bildungswillige leben, sondern auch hinreichende Zahlen von Bekloppten. Das darf ich so locker formulieren, ich bin ja jetzt Rentner und muss nicht mehr auf jedes Wort achten.“
    — Joachim Gauck über Impfgegner
  2. Tach!

    Wie behandelt PHP Whitespaces genau und wann ist trim() notwendig?

    PHP hat keinen eingebauten Mechanismus, String automatisch zu verändern. trim() ist genauso wie alle andere Stringverarbeitung nur dann nötig, wenn du einen fachlichen Grund dafür siehst.

    Abgesehen davon gibt es noch technische Gründe beim Kontextwechsel, wenn Anweisungen/Code und Nutzdaten in einem String zusammengefügt werden sollen (z.B. SQL-Statements oder HTML). Dann müssen die Regeln des jeweiligen Codes beachtet werden, ansonsten entstehen Parsefehler oder unerwüschte Ergebnise (auch sicherheitsrelevante).

    dedlfix.

  3. Hello,

    ...und PHP-seitig (für Testzwecke) nur mal via file_get_contents zurückgeschickt (in der Anwendung dann wohl eher mit FormData):

    // testing_php_trim.php
    <?php
    $content = trim(file_get_contents("php://input"));
    echo $content;
    echo "\n";
    echo trim($content);
    ?>
    

    ...auch hier scheint ein automatisches trim() zu passieren, beide $contents werden clientseitig in der Konsole gleich ausgegeben.

    Du hast doch auch trim(file_get_contents("php://input")) notiert.

    Da wird der Eingabestream eben vorne und hinten um die in trim() voreingestellten Bytes gekürzt. Ich benutze hier "Bytes", weil trim()eine Single-Byte-Funktion ist.

    Vergleiche hierzu auch die mb_*-Funktionen. Für trim() kann ich aber keine entsprechende finden.

    Glück Auf
    Tom vom Berg

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

      nee, das scheint man per Regex lösen zu müssen. Ist aber nicht trivial, wenn ich mich so bei StackOverflow umschaue.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hello,

        nee, das scheint man per Regex lösen zu müssen. Ist aber nicht trivial, wenn ich mich so bei StackOverflow umschaue.

        Na, oder eben mit so 'nem Algendingsbums aus der Tiefsee der Programmierung (Parser). Schließlich sind RegExen und ihre Maschine nix Anderes.

        Glück Auf
        Tom vom Berg

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

          öhm - das wird jetzt aber eine lange Tangente… Diese Gleichheiten sind so nicht gegeben. Einen Parser zu verwenden um Spaces zu entfernen, tja, das geht sicherlich. Ich kann auch mit dem 40-Tonner losfahren, um einen Kasten Bier zu kaufen.

          • Ein Parser verwendet als Vorstufe einen Lexer.
          • Ein Lexer verwendet Regexe zum Auffinden der Lexeme (zumindest ist das in dem mir bekannten Parsergenerator Antlr so)
          • Eine Regex-Library verwendet mutmaßlich einen Parser, um Regex-Sourcecode in die interne Darstellung umzusetzen.
          • Die interne Darstellung ist im einfachen Fall ein endlicher Automat - was aber bei modernen Regex auf Probleme läuft, weil ein endlicher Automat reguläre Sprachen abbilden kann (->Chomsky-Hierarchie), und eine Regex trotz ihres Namens nicht regulär ist. Für die heutigen Regexe braucht man komplexere Maschinen.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. @@Rolf B

            • Die interne Darstellung ist im einfachen Fall ein endlicher Automat - was aber bei modernen Regex auf Probleme läuft, weil ein endlicher Automat reguläre Sprachen abbilden kann (->Chomsky-Hierarchie), und eine Regex trotz ihres Namens nicht regulär ist. Für die heutigen Regexe braucht man komplexere Maschinen.

            Das hab ich letztens im kleinen Kreis erzählt: RegExp ≠ regular expression.

            Und da vieles hier aus dem Forum gezeigt: What a RegExp!

            😷 LLAP

            --
            „Dann ist ja auch schrecklich, dass wir in einem Land leben, in dem nicht nur Bildungswillige leben, sondern auch hinreichende Zahlen von Bekloppten. Das darf ich so locker formulieren, ich bin ja jetzt Rentner und muss nicht mehr auf jedes Wort achten.“
            — Joachim Gauck über Impfgegner
    2. Ich habe „ideenhalber“ mal versucht, eine auf Arrays basierende Funktion zu schreiben, die mit UTF-Symbolen kann. Diese scheint zu funktionieren, mir auch ausreichend schnell zu sein - ist aber noch nicht genügend getestet.

      Weshalb ich das Zeug ausdrücklich als „bad“ („schlecht“, „nicht verwenden”) markiere:

      <?php
      
      $nbsp = chr(0xC2).chr(0xA0);
      $string = '🛠' . $nbsp . 'äüöödäipusö🛠' . $nbsp . 'öäü';
      $toTrim = '🛠öä' . $nbsp . 'ü';
      
      echo 'Zu durchsuchender String (HTML-kodiert:)'. PHP_EOL;
      echo "\t". '"' . htmlentities( $string, ENT_HTML5 ) .'"' . PHP_EOL . PHP_EOL;
      
      echo' Zu entfernende Zeichen: (HTML-kodiert:)' . PHP_EOL;
      echo "\t". '"' . htmlentities( $toTrim, ENT_HTML5 ) .'"' . PHP_EOL . PHP_EOL;
      
      echo 'Ergebnis: "' .  raketen_trim( $string, $toTrim ) . '"' . PHP_EOL;
      
      $rounds = 1000000;
      $start = microtime(true);
      for ($i=0; $i<$rounds; $i++) {
      	raketen_trim( $string, $toTrim ) . PHP_EOL;
      }
      echo  round( ( microtime(true) - $start) * 1000)  . ' Millisekunden für ' . $rounds . ' Runden.'  .  PHP_EOL;
      
      
      
      
      function raketen_trim( $string, $toTrim ) {
      
      	if ( '' == $string ) return '';
      
      	if ( ! is_array( $toTrim ) ) {
      		$arToTrim = mb_str_split( $toTrim );
      	}
      	if ( ! count($arToTrim ) ) return $string;
      
      	$arString = mb_str_split( $string );
      
      	$changed = true;
      	while ( $changed ) {
      		$changed = false;
      		if (  in_array( $arString[ 0 ], $arToTrim ) ) {
      			array_shift( $arString );
      			if (0 == count( $arString ) ) return '';
      			$changed = true;
      			
      		}
      		if ( in_array( $arString[ sizeof($arString) -1 ], $arToTrim ) ) {
      			array_pop( $arString );
      			if (0 == count( $arString ) ) return '';
      			$changed = true;			
      		}
      	}
      	return implode( '', $arString );
      }
      

      Ausgaben: (Die Leerzeichen sind "geschützte Leerzeichen"):

      Zu durchsuchender String (HTML-kodiert:)
      	"🛠&nbsp;&auml;&uuml;&ouml;&ouml;d&auml;ipus&ouml;🛠&nbsp;&ouml;&auml;&uuml;"
      
       Zu entfernende Zeichen: (HTML-kodiert:)
      	"🛠&ouml;&auml;&nbsp;&uuml;"
      
      Ergebnis: "däipus"
      10226 Millisekunden für 1000000 Runden.
      

      Wettbewerb(e):

      1. Fehler finden
      2. eine schnellere (und funktionierende) Funktion schreiben
      1. Hallo Raketenwilli,

        lässt Du das auf einem RASPI laufen?

        2611 Millisekunden für 1000000 Runden.

        Und mein Hobel ist steinalt (Core i5-3470)

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Nö. lscpu behauptet:

          AMD Ryzen 7 2700 Eight-Core Processor

          Das System ist aber so konfiguriert, dass der wegen der kurzen Belastung nicht erst aus dem Stromsparmodus geht.

          CPU MHz:                         1550.000
          
          Stepping:                        2
          Frequenzanhebung:                aktiviert
          CPU MHz:                         1550.000
          

          und ich hatte php-xdebug an Start. Das ha ich jetzt mal abgeschaltet:

          Verbesserungen: (immer noch nicht genug getestet!)

          <?php
          ### file: mb_trim.php
          
          if ( ! function_exists ( 'mb_trim' ) ) {
          	function mb_trim( $string, $toTrim ) {
          
          		if ( '' == $string ) return '';
          		if ( ! is_array( $toTrim ) ) {
          			$arToTrim = mb_str_split( $toTrim );
          		}
          		if ( ! count( $arToTrim ) ) return $string;
          
          		$arString = mb_str_split( $string );
          
          		$changed = true;
          		while ( $changed ) {
          			$changed = false;
          			if ( in_array( $arString[ 0 ], $arToTrim ) ) {
          				array_shift( $arString );
          				if (0 == count( $arString ) ) return '';
          				$changed = true;
          				
          			}
          			if ( in_array( $arString[ count( $arString ) -1 ], $arToTrim ) ) {
          				array_pop( $arString );
          				if (0 == count( $arString ) ) return '';
          				$changed = true;			
          			}
          		}
          		return implode( '', $arString );
          	}
          } else {
          	trigger_error( 'The function "mb_trim" exists! Pleace check your script(s)!', E_USER_ERROR );
          }
          
          if ( ! function_exists ( 'mb_rtrim' ) ) {
          	function mb_rtrim( $string, $toTrim ) {
          
          		if ( '' == $string ) return '';
          		if ( ! is_array( $toTrim ) ) {
          			$arToTrim = mb_str_split( $toTrim );
          		}
          		if ( ! count( $arToTrim ) ) return $string;
          
          		$arString = mb_str_split( $string );
          
          		$changed = true;
          		while ( $changed ) {
          			$changed = false;
          			if ( in_array( $arString[ count( $arString ) -1 ], $arToTrim ) ) {
          				array_pop( $arString );
          				if (0 == count( $arString ) ) return '';
          				$changed = true;			
          			}
          		}
          		return implode( '', $arString );
          	}
          } else {
          	trigger_error( 'The function "mb_rtrim" exists! Pleace check your script(s)!', E_USER_ERROR );
          }
          
          if ( ! function_exists ( 'mb_ltrim' ) ) {
          	function mb_ltrim( $string, $toTrim ) {
          
          		if ( '' == $string ) return '';
          		if ( ! is_array( $toTrim ) ) {
          			$arToTrim = mb_str_split( $toTrim );
          		}
          		if ( ! count( $arToTrim ) ) return $string;
          
          		$arString = mb_str_split( $string );
          
          		$changed = true;
          		while ( $changed ) {
          			$changed = false;
          			if ( in_array( $arString[ 0 ], $arToTrim ) ) {
          				array_shift( $arString );
          				if (0 == count( $arString ) ) return '';
          				$changed = true;
          				
          			}
          		}
          		return implode( '', $arString );
          	}
          } else {
          	trigger_error( 'The function "mb_ltrim" exists! Pleace check your script(s)!', E_USER_ERROR );
          }
          

          Tests:

          <?php
          require_once ('mb_trim.php');
          
          $rounds = 100000;
          $nbsp = chr(0xC2).chr(0xA0);
          $string = '🛠' . $nbsp . 'äüöödäipusö🛠' . $nbsp . 'öäü';
          $toTrim = '🛠öä' . $nbsp . 'ü';
          
          echo 'Zu durchsuchender String (HTML-kodiert:)'. PHP_EOL;
          echo "\t". '"' . htmlentities( $string, ENT_HTML5 ) .'"' . PHP_EOL . PHP_EOL;
          
          echo' Zu entfernende Zeichen: (HTML-kodiert:)' . PHP_EOL;
          echo "\t". '"' . htmlentities( $toTrim, ENT_HTML5 ) .'"' . PHP_EOL . PHP_EOL;
          
          echo 'Ergebnis für mb_trim(): "'  .  mb_trim( $string, $toTrim ) . '"' . PHP_EOL;
          echo 'Ergebnis für mb_rtrim(): "' .  mb_rtrim( $string, $toTrim ) . '"' . PHP_EOL;
          echo 'Ergebnis für mb_ltrim(): "' .  mb_ltrim( $string, $toTrim ) . '"' . PHP_EOL;
          
          
          echo PHP_EOL . 'Zeitmessung:'. PHP_EOL;
          
          ####################################################
          echo PHP_EOL . 'mb_trim:'  .PHP_EOL;
          
          $start = microtime(true);
          for ($i=0; $i<$rounds; $i++) {
          	mb_trim( $string, $toTrim ) . PHP_EOL;
          }
          
          $time = ( microtime(true) - $start )  ;
          echo $time .  PHP_EOL;
          echo  round( $time * 1000)  . ' Millisekunden für ' . $rounds . ' Runden. (' . round($time/$rounds * 1000000) . ' Mikrosekunden pro Aufruf).' .  PHP_EOL;
          
          ####################################################
          echo PHP_EOL . 'mb_rtrim:'  . PHP_EOL;
          
          $start = microtime(true);
          for ($i=0; $i<$rounds; $i++) {
          	mb_rtrim( $string, $toTrim ) . PHP_EOL;
          }
          
          $time = ( microtime(true) - $start )  ;
          echo $time .  PHP_EOL;
          echo  round( $time * 1000)  . ' Millisekunden für ' . $rounds . ' Runden. (' . round($time/$rounds * 1000000) . ' Mikrosekunden pro Aufruf).' .  PHP_EOL;
          
          ####################################################
          echo PHP_EOL . 'mb_ltrim:'  . PHP_EOL;
          $start = microtime(true);
          for ($i=0; $i<$rounds; $i++) {
          	mb_ltrim( $string, $toTrim ) . PHP_EOL;
          }
          
          $time = ( microtime(true) - $start )  ;
          echo $time .  PHP_EOL;
          echo  round( $time * 1000)  . ' Millisekunden für ' . $rounds . ' Runden. (' . round($time/$rounds * 1000000) . ' Mikrosekunden pro Aufruf).' .  PHP_EOL;
          

          Ausgaben von php -dxdebug.mode=off test_mb_trim.php

          Zu durchsuchender String (HTML-kodiert:)
          	"🛠&nbsp;&auml;&uuml;&ouml;&ouml;d&auml;ipus&ouml;🛠&nbsp;&ouml;&auml;&uuml;"
          
           Zu entfernende Zeichen: (HTML-kodiert:)
          	"🛠&ouml;&auml;&nbsp;&uuml;"
          
          Ergebnis für mb_trim(): "däipus"
          Ergebnis für mb_rtrim(): "🛠 äüöödäipus"
          Ergebnis für mb_ltrim(): "däipusö🛠 öäü"
          
          Zeitmessung:
          
          mb_trim:
          0.26273894309998
          263 Millisekunden für 100000 Runden. (3 Mikrosekunden pro Aufruf).
          
          mb_rtrim:
          0.15137410163879
          151 Millisekunden für 100000 Runden. (2 Mikrosekunden pro Aufruf).
          
          mb_ltrim:
          0.16421294212341
          164 Millisekunden für 100000 Runden. (2 Mikrosekunden pro Aufruf).
          

          Jetzt lachst Du nicht mehr :-)

      2. Hallo Raketenwilli,

        erste naive Lösung, die auf die Array-Konvertierung verzichtet und mb_-Funktionen nutzt:

        function rolfb_trim( $string, $toTrim ) {
        
          if (!is_string($string)) return false;
          if (!is_string($toTrim) || $toTrim == '') return $string;
        
          $len  = mb_strlen($string);
        	
          for ($start = 0;
               $start < $len && mb_strpos($toTrim, mb_substr($string, $start, 1), 0) !== false;
               $start++);
        		 
          for ($end = $len - 1;
               $end > $start && mb_strpos($toTrim, mb_substr($string, $end, 1), 0) !== false;
               $end--);
        
          return mb_substr($string, $start, $end-$start+1);
        }
        

        Die ist auf meinem PC ca 15% schneller. Lasse ich den input-String auf ein "x" enden, so dass sie keinen end-Trim machen muss, ist sie sogar doppelt so schnell. Verlängere ich den input-String mit str_repeat um 500 Zeichen (in der Mitte), wird sie (mit x am Ende) viermal so schnell. Offenbar ist mb_substr eine Schnecke.

        Also habe ich deine und meine Lösung gemixt:

        function rolf_trim2( $string, $toTrim ) {
        
        	if (!is_string($string)) return false;
        	if (!is_string($toTrim) || $toTrim == '') return $string;
        
        	$arString = mb_str_split( $string );
            $len  = count($arString);
        	
        	for ($start = 0;
        		 $start < $len && mb_strpos($toTrim, $arString[$start]) !== false;
        		 $start++);
        		 
        	for ($end = $len-1;
        		 $end > $start && mb_strpos($toTrim, $arString[$end]) !== false;
                 $end--);
        		 
        	return mb_substr($string, $start, $end-$start+1);
        }
        

        Diese Funktion ist konsistent doppelt so schnell wie Deine. Aber die Laufzeit schwankt immer noch proportional zur input-Länge, ich nehme an, der mb_str_split nicht ideal ist. Um das zu lösen, muss man wohl einen UTF-Char Iterator für Strings bauen. Hold my beer...

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          schmeiß das Bier weg - so ein UTF-8 Iterator in PHP ist viel zu langsam (zumindest, wenn man das Iterator-Interface programmiert).

          Damit ist meine trim2 Lösung mein derzeit bestes Angebot.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Ja. Sieht so aus, als wenn Du vorn liegst…

    3. Tach!

      Vergleiche hierzu auch die mb_*-Funktionen. Für trim() kann ich aber keine entsprechende finden.

      Siehe User-Kommentar.

      Wenn es lediglich um Zeichen im ASCII-Bereich geht, kann trim() problemlos auch mit UTF-8 verwendet werden.

      dedlfix.

      1. Hallo,

        Vergleiche hierzu auch die mb_*-Funktionen. Für trim() kann ich aber keine entsprechende finden.

        Wenn es lediglich um Zeichen im ASCII-Bereich geht, kann trim() problemlos auch mit UTF-8 verwendet werden.

        selbstverständlich - aber dann darf man eben nicht erwarten, dass trim() auch die Whitespace-Varianten der Unicode-Vielfalt eliminiert (Zero Width Space, Half Width Space und sowas).

        Möge die Übung gelingen
         Martin

        --
        Darmstadt? Ist das nicht da, wo immer der Urologen-Kongress tagt?
    4. Hi,

      Vergleiche hierzu auch die mb_*-Funktionen. Für trim() kann ich aber keine entsprechende finden.

      für die Version mit einem Parameter braucht's auch bei UTF-8-Strings keine mb-Version.

      Die damit behandelten Zeichen sind alle unterhalb von 7F, haben also genau 1 Byte. Und Zeichen mit Codes oberhalb von 7F haben in den einzelnen Bytes jeweils das höchste Bit gesetzt, sind also höher als 7f, so daß durch trim($string) auch keine anderen Zeichen zerstört werden.

      (bei der Variante mit selbst-angeführten Zeichen ist's was anderes - da funktioniert trim nur richtig, wenn die selbst-angeführten Zeichen alle unterhalb von 7f sind)

      cu,
      Andreas a/k/a MudGuard

  4. Moin,

    ...und zwar verstehe ich nicht ganz, wie sich PHP bezüglich Whitespaces verhält.

    ganz einfach: Gleichgültig.

    <?php
    $eineVar = "   Viele      Leerzeichen ";
     echo $eineVar;
    ?>
    

    ...alle überschüssigen Leerzeichen scheinen in diesem Fall zu verschwinden.

    Wie prüfst du das? In der Browseransicht? Dann ist es nicht PHP, sondern der HTML-Parser des Browsers, der die überschüssigen Leerzeichen verschwinden lässt ("komprimiert").

    // testing_php_trim.php
    <?php
    $content = trim(file_get_contents("php://input"));
    echo $content;
    echo "\n";
    echo trim($content);
    ?>
    

    ...auch hier scheint ein automatisches trim() zu passieren

    Witzbold. Dein PHP-Code lässt erstmal ein trim() auf die Eingabe los, gibt dann das Ergebnis aus, macht dann nochmal ein trim() auf den bereits getrim()-ten String (was an der Stelle nichts mehr zum Abschneiden findet).

    Wie behandelt PHP Whitespaces genau und wann ist trim() notwendig?

    PHP behandelt Whitespace gar nicht, und trim() ist genau dann notwendig, wenn du Whitespace am Anfang und/oder am Ende eines Strings abschneiden willst.

    Möge die Übung gelingen
     Martin

    --
    Darmstadt? Ist das nicht da, wo immer der Urologen-Kongress tagt?
    1. Hello,

      Wie behandelt PHP Whitespaces genau und wann ist trim() notwendig?

      PHP behandelt Whitespace gar nicht, und trim() ist genau dann notwendig, wenn du Whitespace am Anfang und/oder am Ende eines Strings abschneiden willst.

      Spannend bleibt aber die Nebenfrage, wie die Browser mit führenden und anhängenden Whitespaces bei der Übertragung der Parameter aus unterschiedlichen Kontexten und mit unterschiedlichen Methoden umgehen?

      • Wie war das bei <input >-Elementen?
      • Wie ist es bei Textareas?
      • Wie ist es bei File-Data [upload]

      Gibt's sonst noch 'was?

      Mein Wissen dazu ist veraltet, bzw. verschüttet ;-O

      Glück Auf
      Tom vom Berg

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

        Spannend bleibt aber die Nebenfrage, wie die Browser mit führenden und anhängenden Whitespaces bei der Übertragung der Parameter aus unterschiedlichen Kontexten und mit unterschiedlichen Methoden umgehen?

        • Wie war das bei <input >-Elementen?

        Da ich ja beliebigen Text eintragen kann, ist das auch als value erlaubt.

        • Wie ist es bei Textareas?

        Laut https://html.spec.whatwg.org/multipage/rendering.html#the-textarea-element-2 „User agents are expected to apply the 'white-space' CSS property to textarea elements.“ Das ist ja auch sinnvoll, weil ich in eine textarea beliebigen Text eingeben kann.

        Insgesamt einmal demonstriert:

        <input type="text" value="    4    " name="t">
        <textarea>1
        
        2
            3	(4 Leerzeichen)
        	4	(1 Tab)
        5</textarea>
        

        Formular mit dem oben stehenden HTML-Text

        • Wie ist es bei File-Data [upload]

        Da wäre ich sehr verwundert, wenn irgendein Browser den Dateiinhalt manipuliert.

        Viele Grüße
        Robert

        1. Hello,

          ja, genauso wäre es logisch.

          Ich erinnere mich aber daran, dass in einem der Fälle (vermutlich eine der Input-Klassen) trotzdem geschnippelt wurde, zumindest bei trailing whitspaces.

          Kann allerdings auch sein, dass das eine Browsereigenheitunart war.

          Glück Auf
          Tom vom Berg

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

            Ich erinnere mich aber daran, dass in einem der Fälle (vermutlich eine der Input-Klassen) trotzdem geschnippelt wurde, zumindest bei trailing whitspaces.

            Kann allerdings auch sein, dass das eine Browsereigenheitunart war.

            guter Punkt, ich habe mal den Cursor ins input gesetzt um die vier trailing white-space zu zeigen:

            Beispiel mit Leerzeichen in Texteingabfeldern: Leerzeichen bleiben erhalten.

            Viele Grüße
            Robert

            1. Hello,

              Ich erinnere mich aber daran, dass in einem der Fälle (vermutlich eine der Input-Klassen) trotzdem geschnippelt wurde, zumindest bei trailing whitspaces.

              Kann allerdings auch sein, dass das eine Browsereigenheitunart war.

              guter Punkt, ich habe mal den Cursor ins input gesetzt um die vier trailing white-space zu zeigen:

              Beispiel mit Leerzeichen in Texteingabfeldern: Leerzeichen bleiben erhalten.

              Beim aktuellen Firefox (bei mir 97.0.1 64-Bit) wird tatsächlich nix mehr getrimmt.

              
              <?php  
                 $i001 = '';
                 if (isset($_POST['i001'])) { $i001 = $_POST['i001']; }
                 $len = strlen($i001);
                 $mblen = mb_strlen($i001); ## vorher apt install php-mbstring
              ?>
              <!DOCTYPE html>
              <html lang="de">
                <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <title>Whitespaces</title>
                </head>
                <body>
                  <form action="" method="POST" enctype="multipart/form-data">
                    <input name="i001" type="text" size="20" value="<?=htmlspecialchars($i001); ?>"> 
                    <input name="b001" type="submit" value="absenden"><br>
                    Länge = <?=$len; ?><br>
                    MB-Länge = <?=$mblen; ?>
                  </form>
                </body>
              </html>
              
              

              Glück Auf
              Tom vom Berg

              --
              Es gibt nichts Gutes, außer man tut es!
              Das Leben selbst ist der Sinn.
  5. Uff, da hab ich ja eine richtige Lawine losgetreten

    Danke alle Teilnehmenden und deren Innen! :D

    ...stimmt, ich habe file_get_contents bereits ein trim zugeschrieben und dafür ein Witzbold kassiert....

    ...kommt davon, wenn man im Schnellverfahren versucht alle möglichen Optionen durchzuspielen.

    Kommen vom Hudeln die Kinder, können meine Nachfahren und deren Innen eine Nation ausrufen.