Talisphere Talisphere - 1 month ago 8
PHP Question

How to trim all whitespace from string, but preserve a single trailing line break if one exists

I am trying to create a simple php function to behave the same as the php

trim()
function, except that it preserves a single trailing line break if one exists. In addition, it needs to support preserving CRLF, CR and LF cases.

Consider the following use cases:


  1. myTrim(
    " \t \r\n The quick brown fox jumps over the lazy dog \t \t "
    )
    === "The quick brown fox jumps over the lazy dog"

  2. myTrim(
    " \t \r\n The quick brown fox jumps over the lazy dog \t \r\n\r\n \t \r\n "
    )
    === "The quick brown fox jumps over the lazy dog\r\n"

  3. myTrim(
    " \t \r\n The quick brown fox jumps over the lazy dog \t \r\r \t \r "
    )
    === "The quick brown fox jumps over the lazy dog\r"

  4. myTrim(
    " \t \r\n The quick brown fox jumps over the lazy dog \t \n\n \t \n "
    )
    === "The quick brown fox jumps over the lazy dog\n"



I have unsuccessfully tried a function such as:

public static function trimMessageBlock( $block )
{
// Remove all leading whitespace (e.g. HT (9), LF (10), FF (12), CR (13), and space (32))
$block = preg_replace("/^\s+/", "", $block);
// Remove all trailing whitespace, but preserve a single trailing line break if one exists
$block = preg_replace("/\s*(\R?)\s*$/", "$1", $block);

return $block;
}


The above code seems to ignore the line break character entirely, and match only the simple case (
\s*
). The only other way I can see to do this is to use a "if" statement to test for a
/\s*\R\s*$/
pattern first, then either use
/\s*\R\s*$/
or
/\s+$/
, depending on if a newline is present of not. Any suggestions on a simpler, more elegant way to do this in regex?

BTW This is my first post to stackoverflow

Answer

You could do it something like this. (see comments)

<?php

function myTrim($str) {
    //Look for a non whitespace character with whitespace following.
    //Capture the first (either 1 or 2) consecutive line ending characters
    if (preg_match("/[^\s]\s*?([\r\n]{1,2})\s*$/", $str, $capture)) {
        //If the line endings are not /r/n
        if ($capture[1] !== "\r\n") {
            //Only take the first character
            $capture[1] = $capture[1][0];
        }
        //Trim the string and append the found line ending.
        return trim($str) . $capture[1];
    }
    //No line endings were found
    return trim($str);
}

var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \t ") === "The quick brown fox jumps over the lazy dog");
var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \r\n\r\n \t \r\n ") === "The quick brown fox jumps over the lazy dog\r\n");
var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \r\r \t \r ") === "The quick brown fox jumps over the lazy dog\r");
var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \n\n \t \n ") === "The quick brown fox jumps over the lazy dog\n");
//Added a couple more edge test cases
var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \n\r\n \t \n ") === "The quick brown fox jumps over the lazy dog\n");
var_dump(myTrim(" \t \r\n The quick brown fox jumps over the lazy dog \t \r\n\n \t \n ") === "The quick brown fox jumps over the lazy dog\r\n");

//Outputs
//bool(true) bool(true) bool(true) bool(true) bool(true) bool(true)     
Comments