You are handling multibyte strings so additional care must be taken. If you do not include the u
pattern modifier, your multibyte return values will be damaged. (Demo)
Let's dissect your posted patterns:
Patterns to be replaced by a single space:
/\s{2,}/ // match two or more whitespace characters
/[\t\n]/ // then re-iterate the potentially modified string and match any tab or line-feed (newline) character
Rather than making two separate passes, you can safely merge the logic into one pattern. To provide a more comprehensive "mop up" of newline characters, I'll recommend \R
.
/\s{2,}|[\R\t]/u
As for the pattern to remove whitelisted characters, you have some overlapping logic which I believe is due to an ill-positioned hyphen.
Reference: https://www.ascii.cl/htmlcodes.htm
pattern | ASCII decimal place
-----------------------------
[a-z] | range 97 to 122
[A-Z] | range 65 to 90
[0-9] | range 48 to 57
à | 195
§ | 167
[&-©] | range 38 to 169
‚ | 44
 | 194
ƒ | 402
â | 226
€ | 8364
˜ | 126
\s | *(equal to [\p{Z}\h\v]) <-- I don't feel like writing it all out
The position of your hyphen between two non-ranged entities in your negated character class tells the regex engine that you which to declare a range of characters. I interpret this to be a mistake. Rather than escaping the hyphen, I always recommend positioning the hyphen as the final character in the character class.
My suggested pattern will condense the alphabetic ranges by writing the case-insensitive pattern modifier i
, using \d
to signify digits, moving character ranges to the front, moving the hyphen to the back, and then (to be OCD) I've ordered single characters by their decimal value.
/[^a-z\d\s&‚~§©ÂÃ⃀-]/ui
You could implement this without retyping $string
to create a oneliner, but if you prefer shorter lines of code, you can break it up over multiple lines or declare variables.
function stripSpecialCharater($string)
{
return preg_replace(['/\s{2,}|[\t\R]/u', '/[^a-z\d\s&‚~§©ÂÃ⃀-]/ui'], [' ', ''], iconv("Windows-1252", "UTF-8", urldecode($string)));
}
Now we don't have any sample input to work with, but this may be a valuable read. It might be more stable to perform the replacement on the raw string, but that is for you to determine with your project data. There are plenty of ways to mince multibyte characters that are not always obvious; I recommend testing against a large battery of cases.
Raw replacement:
return preg_replace(['/\s{2,}|[\t\R]/u', '/[^a-z\d\s&‚~§©ÂÃ⃀-]/ui'], [' ', ''], $string);
As a final consideration, you may want to perform the whitespace reduction after the whitelist replacements so that you can handle newly consecutive whitespace characters. A final trim()
might be advisable too. Add some realistic test strings to this demo and see what processes ultimately provide the cleanest output.