KDOT KDOT - 2 months ago 9
PHP Question

How to count the first 30 letters in a string ignoring spaces

I want to take a post description but only display the first, for example, 30 letters but ignore any tabs and spaces.

$msg = 'I only need the first, let us just say, 30 characters; for the time being.';
$msg .= ' Now I need to remove the spaces out of the checking.';

$amount = 30;

// if tabs or spaces exist, alter the amount
if(preg_match("/\s/", $msg)) {
$stripped_amount = strlen(str_replace(' ', '', $msg));
$amount = $amount + (strlen($msg) - $stripped_amount);

echo substr($msg, 0, $amount);
echo '<br /> <br />';
echo substr(str_replace(' ', '', $msg), 0, 30);

The first output gives me 'I only need the first, let us just say, 30 characters;' and the second output gives me: Ionlyneedthefirst,letusjustsay so I know this isn't working as expected.

My desired output in this case would be:

I only need the first, let us just say

Thanks in advance, my maths sucks.


You could get the part with the first 30 characters with a regular expression:

$msg_short = preg_replace('/^((\s*\S\s*){0,30}).*/s', '$1', $msg);

With the given $msg value, you will get in $msg_short:

I only need the first, let us just say

Explanation of the regular expression

  • ^: match must start at the beginning of the string
  • \s*\S\s* a non-white-space (\S) surrounded by zero or more white-space characters (\s*)
  • (\s*\S\s*){0,30} repeat finding this sequence up to 30 times (greedy; get as many as possible within that limit)
  • ((\s*\S\s*){0,30}) the parentheses make this series of characters group number 1, which can be referenced as $1
  • .* any other characters. This will match all remaining characters, because of the s modifier at the end:
  • s: makes the dot match new line characters as well

In the replacement only the characters are maintained that belong to group one ($1). All the rest is ignored and not included in the returned string.