252

I'm getting $row['message'] from a MySQL database and I need to remove all whitespace like \n \t and so on.

$row['message'] = "This is   a Text \n and so on \t     Text text.";

should be formatted to:

$row['message'] = 'This is a Text and so on Text text.';

I tried:

 $ro = preg_replace('/\s\s+/', ' ',$row['message']);
 echo $ro;

but it doesn't remove \n or \t, just single spaces. Can anyone tell me how to do that?

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
creativz
  • 10,369
  • 13
  • 38
  • 35

15 Answers15

464

You need:

$ro = preg_replace('/\s+/', ' ', $row['message']);

You are using \s\s+ which means whitespace(space, tab or newline) followed by one or more whitespace. Which effectively means replace two or more whitespace with a single space.

What you want is replace one or more whitespace with single whitespace, so you can use the pattern \s\s* or \s+ (recommended)

Avatar
  • 14,622
  • 9
  • 119
  • 198
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • 2
    his method is better than this: why would you replace one space with one space? – nickf Feb 24 '10 at 13:13
  • 19
    He also wants \n and \t to be replaced with space. Now his pattern does not match these, say for $x = "does\nthis\twork"; The OP wants all whitespace to be replaced with a single space. – codaddict Feb 24 '10 at 13:17
  • 1
    @codaddict, how we can keep \n and remove all other multiple space and tabs from the string? please help me – Mansoorkhan Cherupuzha Sep 20 '13 at 09:20
  • 1
    Can you be more specific why "\s+" is recommended? – Isius Oct 25 '13 at 03:09
  • 7
    Note that in PHP `\s` not including "vertical tab" `chr(11)`. To include it too you need to use `space` character class: `[[:space:]]+` http://www.php.net/manual/en/regexp.reference.character-classes.php – Yaroslav Oct 29 '13 at 18:49
  • keep in mind that this will also replace newlines `\r\n` with a single space ` ` – Timo Huovinen Jan 31 '14 at 10:13
  • $row['message'] = 18; // $ro is null. – e-info128 Mar 06 '14 at 15:00
  • @WHK `preg_replace()` requires the third parameter to be either a string or an array full of strings. Otherwise, it will return `null`, meaning an error occured. `$row['message'] = 18; // $ro = null` **while** `$row['message'] = '18'; // $ro = '18'` **and** `$row['message'] = (string) 18; // $ro = '18'` – Marcello Mönkemeyer Nov 14 '14 at 15:31
  • I want to remove spaces at the beginning or at the end of the text. If the string is `' Text with a lot of spaces '`, it returns `' Text with a lot of spaces '`. I expect `'Text with a lot of spaces'`. – Mai Feb 19 '15 at 10:09
  • I tried using this method, which works, except that instead of " " I get ` `. Normally, this wouldn't matter, but I'm exporting the result text to an Excel spreadsheet, and those ` ` are showing up in the spreadsheet cell. It's bad because the spreadsheet cell text is going to be used to print mailing labels. – TARKUS Jun 15 '16 at 15:34
  • Here's a method that will also remove ` ` preg_replace(array('/\s{2,}| /', '/[\t\n]/'), ' ', $str)` – TARKUS Jun 15 '16 at 16:04
  • @codaddict , nice job, thank you, with keeping this regex pattern, is there a way to get rid of all spaces at the right & and the left of the string? for example, " a b c ", would be "a b c", I know we could use trim($ro), but it would be nice to have it in regex – eawedat Feb 01 '17 at 22:33
78
<?php
$str = "This is  a string       with
spaces, tabs and newlines present";

$stripped = preg_replace(array('/\s{2,}/', '/[\t\n]/'), ' ', $str);

echo $str;
echo "\n---\n";
echo "$stripped";
?>

This outputs

This is  a string   with
spaces, tabs and newlines present
---
This is a string with spaces, tabs and newlines present
uınbɐɥs
  • 7,236
  • 5
  • 26
  • 42
cEz
  • 4,932
  • 1
  • 25
  • 38
18
preg_replace('/[\s]+/mu', ' ', $var);

\s already contains tabs and new lines, so this above regex appears to be sufficient.

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Anonymous
  • 4,692
  • 8
  • 61
  • 91
  • 2
    Square brackets aren't needed here because there's only one thing inside them. The `/m` wont have an effect as there are no `^` or `$` anchors and the `/u` won't have any effect except to slow it down slightly and die if the input string is not valid UTF-8 (it doesn't affect what `\s` matches, but it would affect `\pZ`). – thomasrutter May 17 '16 at 04:18
15

simplified to one function:

function removeWhiteSpace($text)
{
    $text = preg_replace('/[\t\n\r\0\x0B]/', '', $text);
    $text = preg_replace('/([\s])\1+/', ' ', $text);
    $text = trim($text);
    return $text;
}

based on Danuel O'Neal answer.

Lukas Liesis
  • 24,652
  • 10
  • 111
  • 109
10
$str='This is   a Text \n and so on Text text.';
print preg_replace("/[[:blank:]]+/"," ",$str);
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
10

I can't replicate the problem here:

$x = "this    \n \t\t \n    works.";
var_dump(preg_replace('/\s\s+/', ' ', $x));
// string(11) "this works."

I'm not sure if it was just a transcription error or not, but in your example, you're using a single-quoted string. \n and \t are only treated as new-line and tab if you've got a double quoted string. That is:

'\n\t' != "\n\t"

Edit: as Codaddict pointed out, \s\s+ won't replace a single tab character. I still don't think using \s+ is an efficient solution though, so how about this instead:

preg_replace('/(?:\s\s+|\n|\t)/', ' ', $x);
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 3
    +1, True. For a string with plenty of single spaces (which usually is the case) it is inefficient to replace a space with space. – codaddict Feb 24 '10 at 13:32
  • 2
    @coaddict: to test your hypothesis, i wrote a quick script to run through 1000 of each replacement and check the timing of each. For the string **'+1, True. For a string with plenty of single spaces (which usually is the case) it is inefficient to replace a space with space. – codaddict Feb 24 \'10 at 13:32'**, one thousand **\s+** preg_replace() calls took 0.010547876358032 seconds, and one thousand **(?:\s\s+|\n|\t)** preg_replace() calls took 0.013049125671387, making it almost 30% slower. – Joseph Cheek May 01 '14 at 23:31
  • You may want to add "\r" to that last example as some computers do use a single "\r" on its own (Apple Mac?) – thomasrutter May 17 '16 at 04:26
6
preg_replace('/(\s\s+|\t|\n)/', ' ', $row['message']);

This replaces all tabs, all newlines and all combinations of multiple spaces, tabs and newlines with a single space.

middus
  • 9,103
  • 1
  • 31
  • 33
  • `\t` & `\n` are already included in `\s` so your regex is **exactly** the same than `\s\s+` that is better written `\s{2,}` just like @Alex Polo [answer](https://stackoverflow.com/a/3127205/372239) – Toto Mar 08 '21 at 12:41
  • I needed the same functionality as in the original question only without replacing the single space with single space character and this is the solution – 6opko Oct 11 '22 at 13:48
4
<?php
#This should help some newbies
# REGEX NOTES FROM DANUEL
# I wrote these functions for my own php framework
# Feel Free to make it better
# If it gets more complicated than this. You need to do more software engineering/logic.
# (.)  // capture any character
# \1   // if it is followed by itself
# +    // one or more

class whitespace{

    static function remove_doublewhitespace($s = null){
           return  $ret = preg_replace('/([\s])\1+/', ' ', $s);
    }

    static function remove_whitespace($s = null){
           return $ret = preg_replace('/[\s]+/', '', $s );
    }

    static function remove_whitespace_feed( $s = null){
           return $ret = preg_replace('/[\t\n\r\0\x0B]/', '', $s);
    }

    static function smart_clean($s = null){
           return $ret = trim( self::remove_doublewhitespace( self::remove_whitespace_feed($s) ) );
    }
}
$string = " Hey   yo, what's \t\n\tthe sc\r\nen\n\tario! \n";
echo whitespace::smart_clean($string);
Danuel O'Neal
  • 304
  • 3
  • 4
  • 3
    static function remove_whitespace is for what reason? You define but never use it. – Lukas Liesis May 29 '15 at 11:37
  • 1
    These each have their use but none of these would achieve what the question asks for which is to replace multiple consecutive whitespace with just one. Your "remove_doublewhitespace" would only replace multiple of *the same* whitespace character, so it would replace "\n\n\n" with a ' ', but it would not do anything to " \r\n" – thomasrutter May 17 '16 at 04:22
4

Without preg_replace()

$str = "This is   a Text \n and so on \t     Text text.";
$str = str_replace(["\r", "\n", "\t"], " ", $str);
while (strpos($str, "  ") !== false)
{
    $str = str_replace("  ", " ", $str);
}
echo $str;
hharek
  • 41
  • 3
3

This is what I would use:

a. Make sure to use double quotes, for example:

$row['message'] = "This is   a Text \n and so on \t     Text text.";

b. To remove extra whitespace, use:

$ro = preg_replace('/\s+/', ' ', $row['message']); 
echo $ro;

It may not be the fastest solution, but I think it will require the least code, and it should work. I've never used mysql, though, so I may be wrong.

matsolof
  • 2,665
  • 3
  • 18
  • 17
2

I use this code and pattern:

preg_replace('/\\s+/', ' ',$data)

$data = 'This is   a Text 
   and so on         Text text on multiple lines and with        whitespaces';
$data= preg_replace('/\\s+/', ' ',$data);
echo $data;

You may test this on http://writecodeonline.com/php/

Catalin T.
  • 29
  • 2
  • 1
    It works with me even in mariaDB in this query: `SELECT search_able, REGEXP_REPLACE (search_able,"\\s+",' ') FROM book where id =260` So Thanks a lot – jalmatari Sep 28 '19 at 18:17
2

All you need is to run it as follows:

echo preg_replace('/\s{2,}/', ' ', "This is   a Text \n and so on \t     Text text."); // This is a Text and so on Text text.
Alex Polo
  • 905
  • 9
  • 21
1

On the truth, if think that you want something like this:

preg_replace('/\n+|\t+|\s+/',' ',$string);
BigBlast
  • 397
  • 1
  • 11
1

this will replace multiple tabs with a single tab

preg_replace("/\s{2,}/", "\t", $string);
Heman G
  • 75
  • 1
  • 12
-4

Without preg_replace, with the help of loop.

<?php

$str = "This is   a Text  and so on      Text text.";
$str_length = strlen($str);
$str_arr = str_split($str);
for ($i = 0; $i < $str_length; $i++) {
    if (isset($str_arr[$i + 1])
       && $str_arr[$i] == ' '
       && $str_arr[$i] == $str_arr[$i + 1]) {
       unset($str_arr[$i]);
    } 
    else {
      continue;
    }
}

 echo implode("", $str_arr) ; 

 ?>