views:

102

answers:

7

I've this PHP regular expression:

$username = preg_replace('/[^a-z0-9]/i', '', $username);

It allows only A-Z and 0-9. How can I allow ., - and _ as well?

+1  A: 
$username = preg_replace('/[^a-z0-9._-]/i', '', $username);

Removes anything that isn't ([^]) one of the characters on the group. Note the hypern is the last one there, so it loses its special meaning.

Kobi
I always thought a hyphen only meant something when between letters or numbers - what would `$username = preg_replace('/[^_-.]/i', '', $username);` do?
Dominic Rodger
it will mind characters **between** `_` and `.`, which is just weird.
Kobi
@Kobi - interesting - so presumably all characters with decimal values between 95 (`_`) and 46 (`.`)? Wonder if that would equate to `.-_`.
Dominic Rodger
Also, someone checked and found that `/[^a-z0-9._-]+/i` is better here, but that's optimizing.
Kobi
+1  A: 

If you know exactly what you need to match, just specify it in a character group. The dash either needs to be at the very start or very end.

/[A-Z0-9._-]/
ar
In the answer that was deleted, you said that escaping the DOT will cause the backslash to be matched too, this is not true. Try it: `preg_match_all('/[\.]/', '.\\', $matches); print_r($matches);` Adding a single backslash does nothing, it will just match the literal DOT inside a character class.
Bart Kiers
Since preg_replace() is being used they would need to negate this.
jasonbar
+1  A: 
$username = preg_replace('/[^a-z0-9._-]/i', '', $username);

Your current code actually does allow both A-Z and a-z - the i flag marks your regular expression as case-insensitive.

Dominic Rodger
+6  A: 

You can use the following regex:

/[^a-z0-9._-]/i
  • i at the end is to make the pattern matching case-insensitive. You can drop it and use: /[^a-zA-Z0-9._-]/
  • -(hyphen) has a special meaning in char class if its surrounded on both sided so we put it at the end so that its treated literally. You can also do: /[^a-z0-9.\-_]/ where we are escaping the hyphen
  • A dot in a char class is not a meta char hence will be treated literally and need not be escaped.
codaddict
+1 from me - most complete answer so far.
Dominic Rodger
This needs to be negated as well.. `preg_replace()` and all..
jasonbar
@jsonbar: Thanks for pointing.
codaddict
{"@":"codaddict","msg":"No problem."} eh eh eh...
jasonbar
Why is this regex winking at me? O_O;;
deceze
A: 
$username = preg_replace('/[^a-z0-9._-]/i', '', $username);
dale
+2  A: 

Try

$username = preg_replace('/[^a-z0-9.-_]/i', '', $username);
Jojo Sardez
You need to escape the last hyphen as : .\-_
codaddict
+1  A: 

Easy, just add those characters to the regular expression as well

$username = preg_replace('/[^a-zA-Z0-9._-]/','',$username)

The . needs to be escaped because its the 'matchall' character, the - goes in the end because otherwise it would be used to define a range (we could ofcourse have just escaped it).

Kristoffer S Hansen
The `.` doesn't need escaping inside a character group.
Dominic Rodger
I did not know that, thanks.
Kristoffer S Hansen