PHP Regular expression - Remove all non-alphanumeric characters

20,214

Solution 1

You can try this:

preg_replace('~[^\p{L}\p{N}]++~u', ' ', $string);

\p{L} stands for all alphabetic characters (whatever the alphabet).

\p{N} stands for numbers.

With the u modifier characters of the subject string are treated as unicode characters.

Or this:

preg_replace('~\P{Xan}++~u', ' ', $string);

\p{Xan} contains unicode letters and digits.

\P{Xan} contains all that is not unicode letters and digits. (Be careful, it contains white spaces too that you can preserve with ~[^\p{Xan}\s]++~u )

If you want a more specific set of allowed letters you must replace \p{L} with ranges in unicode table.

Example:

preg_replace('~[^a-zÀ-ÖØ-öÿŸ\d]++~ui', ' ', $string);

Why using a possessive quantifier (++) here?

~\P{Xan}+~u will give you the same result as ~\P{Xan}++~u. The difference here is that in the first the engine records each backtracking position (that we don't need) when in the second it doesn't (as in an atomic group). The result is a small performance profit.

I think it's a good practice to use possessive quantifiers and atomic groups when it's possible.

However, the PCRE regex engine makes automatically a quantifier possessive in obvious situations (example: a+b => a++b) except If the PCRE module has been compiled with the option PCRE_NO_AUTO_POSSESS. (http://www.pcre.org/pcre.txt)

More informations about possessive quantifiers and atomic groups here (possessive quantifiers) and here (atomic groups) or here

Solution 2

Are you perhaps looking for \W?

Something like:

/[\W_]*/

Matches all non-alphanumeric character and underscores.

\w matches all word character (alphabet, numeric, underscores)

\W matches anything not in \w.

So, \W matches any non-alphanumeric characters and you add the underscore since \W doesn't match underscores.

EDIT: This make your line of code become:

preg_replace("/[\W_]*/", ' ', $string);

The ' ' means that all matching characters (those not letter and not number) will become white spaces.

reEDIT: You might additionally want to use another preg_replace to remove all the consecutive spaces and replace them with a single space, otherwise you'll end up with:

This is a string test width     and some  ber strange characters   like this 

You can use:

preg_replace("/\s+/", ' ', $string);

And lastly trim the beginning and end spaces if any.

Solution 3

I am not entirely sure which variety of regex you are using. However, POSIX regexes allow you to express an alphabetical class, where [:alpha:] represents any alphabetic character.

So try:

preg_replace("/[^[:alpha:]0-9 ]/", '', $string);

Actually, I forgot about [:alnum:] - that makes it simpler:

preg_replace("/[^[:alnum:] ]/", '', $string);

Solution 4

\p{xx} is what you are looking for, I believe, see here

So, try:

preg_replace("/\P{L}+/u", ' ', $string);
Share:
20,214
Jens Törnell
Author by

Jens Törnell

Updated on May 06, 2020

Comments

  • Jens Törnell
    Jens Törnell about 4 years

    I use PHP.

    My string can look like this

    This is a string-test width åäö and some über+strange characters: _like this?

    Question

    Is there a way to remove non-alphanumeric characters and replace them with a space? Here are some non-alphanumeric characters:

    • -
    • +
    • :
    • _
    • ?

    I've read many threads about it but they don't support other languages, like this one:

    preg_replace("/[^A-Za-z0-9 ]/", '', $string);
    

    Requirements

    • My list of none letter characters might not be complete.
    • My content contain characters in different languages, like åäöü. Could be very many more.
    • The non-alphanumeric characters should be replaced with a space. Else the word would be glued to eachother.
  • Wrikken
    Wrikken about 11 years
    This. However, depending how on the string, one might want to include \X.
  • Jerry
    Jerry about 11 years
    But doesn't this replace all the alphabetic characters that the OP wants to leave as is by space?
  • femtoRgon
    femtoRgon about 11 years
    This should not replace any alphabetic characters, no (note the uppercase P).
  • Jerry
    Jerry about 11 years
    Oh, right. But then, what about numeric characters? Are they included in L? I'm not sure what the documentation means by 'modifier letter' or 'other letter'.
  • MZaragoza
    MZaragoza over 9 years
    @CasimiretHippolyte Thanks for this post, it help me allot I like your regex preg_replace('~[^a-zÀ-ÖØ-öÿŸ\d]++~ui', ' ', $string); but i was wondering how I can add "_" underscores and "-" hyphens in the string to keep
  • Casimir et Hippolyte
    Casimir et Hippolyte over 9 years
    @MoisesZaragoza: If you want to keep these characters, you only need to add them to the character class since it is a negative character class (due to the ^ at the begining, only characters not present in the class are matched and replaced). So ~[^a-zÀ-ÖØ-öÿŸ\d_-]++~ui or ~[^\p{L}\p{N}_-]++~u or ~[^\p{Xan}_-]++~u
  • Casimir et Hippolyte
    Casimir et Hippolyte over 9 years
    @MoisesZaragoza: Note that with Ruby, you can use \p{alnum} (for all unicode letters and digits) and a class intersection: [\P{alnum}&&[^_-]]