Replace all non printable characters except newline characters

Viewed 282

I want to replace all non printable characters, especially emojis from a text but want to retain the newline characters like \n and \r

I currently have this for escaping the non printable characters but it escapes \n and \r also:

preg_replace('/[[:^print:]]/', '', $value);
3 Answers

[:print:] is a POSIX character class for printable chars. If you use it in a negated character class, you can further add characters that you do not want to match with this pattern, i.e. you can use

preg_replace('/[^\r\n[:print:]]/', '', $value)

See the PHP demo:

$value = "One\tline\r\nThe second line";
echo preg_replace('/[^\r\n[:print:]]/', '', $value);
// => Oneline
//    The second line

The [^\r\n[:print:]] pattern matches all chars but printable, CR and LF chars.

The general idea for a regex to "match something, but not when something else" is to first match the "something else" and then instruct the engine to skip it.

So something like...

preg_replace('/[\r\n](*SKIP)(*FAIL)|[[:^print:]]/', '', $value);

This matches newline characters, and then discards the match. Any other non-printable characters are still matched by the second half, and replaced with the empty string.

I think this would do it:

preg_replace('/(?![\r\n])[[:^print:]]/', '', $value);
  • (?![\r\n]) - make sure the next char is not \r nor \n
  • [[:^print:]] - capture the non-printable char

An alternate solution with reversed logic to achieve the same goal would like this:

preg_replace('/(?=[^\r\n])[[:^print:]]/', '', $value);
Related