I'm trying to understand what's wrong with this regex pattern:
'/^[a-z0-9-_\.]*[a-z0-9]+[a-z0-9-_\.]*{4,20}$/i'
What I'm trying to do is to validate the username. Allowed chars are alphanumeric, dash, underscore, and dot. The restriction I'm trying to implement is to have at least one alphanumeric character so the user will not be allowed to have a nickname like this one: _-_.
The function I'm using right now is:
function validate($pattern, $string){
return (bool) preg_match($pattern, $string);
}
Thanks.
EDIT
As #mario said, yes,t here is a problem with *{4,20}.
What I tried to do now is to add ( ) but this isn't working as excepted:
'/^([a-z0-9-_\.]*[a-z0-9]+[a-z0-9-_\.]*){4,20}$/i'
Now it matches 'aa--aa' but it doesn't match 'aa--' and '--aa'.
Any other suggestions?
EDIT
Maybe someone wants to deny not nice looking usernames like "_..-a".
This regex will deny to have consecutive non alphanumeric chars:
/^(?=.{4,20}$)[a-z0-9]{0,1}([a-z0-9._-][a-z0-9]+)*[a-z0-9.-_]{0,1}$/i
In this case _-this-is-me-_ will not match, but _this-is-me_ will match.
Have a nice day and thanks to all :)
Don't try to cram it all into one regex. Make your life simpler and use a two step-approach:
return (bool)
preg_match('/^[a-z0-9_.-]{4,20}$/', $s) && preg_match('/\w/', $s);
The mistake in your regex probably was the mixup of * and {n,m}. You can have only one of those quantifiers, not *{4,20} both after another.
Very well, here is the cumbersome solution to what you want:
preg_match('/^(?=.{4})(?!.{21})[\w.-]*[a-z][\w-.]*$/i', $s)
The assertions assert the length, and the second part ensures that at least one letter is present.
Try this one instead:
'/[a-z0-9-_\.]*[a-z0-9]{1,20}[a-z0-9-_\.]*$/i'
Its probably just a matter if finetuning, you could try something like this:
if (preg_match('/^[a-zA-Z0-9]+[_.-]{0,1}[a-zA-Z0-9]+$/m', $subject)) {
# Successful match
} else {
# Match attempt failed
}
Matches:
a_b <- you might not want this.
ysername
Username
1254_2367
fg3123as
Non-Matches:
l__asfg
AHA_ar3f!
sAD_ASF_#"#T_
"#%"&#"E
__-.asd
username
1___
Non-matches you might want to be matches:
1_5_2
this_is_my_name
It is clear to me that you should split this into two checks!
Firstly check that they are using all valid characters. If they're not, then you can tell them that they are using invalid characters.
Then check that they have at least one alpha-numeric character. If they're not, then you can tell them that they must.
Two distinct advantages here: more meaningful feedback to the user and cleaner code to read and maintain.
Here is a simple, single regex solution (verbose):
$re = '/ # Match password having at least one alphanum.
^ # Anchor to start of string.
(?=.*?[A-Za-z0-9]) # At least one alphanum.
[\w\-.]{4,20} # Match from 4 to 20 valid chars.
\z # Anchor to end of string.
/x';
In Action (short form):
function validate($string){
$re = '/^(?=.*?[A-Za-z0-9])[\w\-.]{4,20}\z/';
return (bool) preg_match($re, $string);
}
Try this:
^[a-zA-Z][-\w.]{0,22}([a-zA-Z\d]|(?<![-.])_)$
From related question: Create one RegEx to validate a username
^[A-Za-z][A-Za-z0-9]*(?=.{3,31}$)[a-z0-9]{0,1}([a-z0-9._-][a-z0-9]+)*[a-z0-9.-_]{0,1}$
This will Validate the username
start with an alpha
accept underscore dash and dots
no spaces allowed
Why don't you make it simpler like this?
^[a-zA-Z][a-zA-Z0-9\._-]{3,9}
First letter should be Alphabetical.
then followed by character or symbols you allowed
length of the word should be between 4,10 (as explicitly force the first word)
Related
I've got some issues understanding this regex.
I tried doing a pattern but does not work like intended.
What I want is [A-Za-z]{2,3}[0-9]{2,30}
That is 2-3 letters in the beginning and 2-30 numbers after that
FA1321321
BFA18098097
I want to use it to validate an input field but can't figure out how the regex should look like.
Can any one that can help me out even explain a bit about it?
Your regex is correct - just make sure to surround it with / in PHP, and perhaps ^, $ if you want it to strictly match the entire string (no extra characters before/after).
$pattern = "/^[A-Za-z]{2,3}[0-9]{2,30}$/"
$found = preg_match($pattern, $your_str);
From the PHP documentation:
preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.
I searched everywhere but i couldn't find the right regex for my verificaiton
I have a $string, i want to make sure it contains at last one uppercase letter and one number. no other characters allowed just numbers and letter. is for a password require.
John8 = good
joHn8 = good
jo8hN = good
I will use preg_match function
The uppercase and letter can be everywhere in the word, not only at the begging or end
This should work, but is a bit of a mess. Consider using multiple checks for readability and maintainability...
preg_match('/^[A-Za-z0-9]*([A-Z][A-Za-z0-9]*\d|\d[A-Za-z0-9]*[A-Z])[A-Za-z0-9]*$/', $password);
Use lookahead:
preg_match('/^(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$/', $string);
Use this regex pattrn
^([A-Z]+([a-z0-9]+))$
Preg_match
preg_match('~^([A-Z]+([a-z0-9]+))$~',$str);
Demo
Your requisition need "precise syntax description", and a lot of examples for assert your description. Only 3 or 4 examples is not enough, is very open.
For last confirmed update:
preg_match('/^([a-z]*\d+[a-z]*[A-Z][a-z]*|[a-z]*[A-Z][a-z]*\d+[a-z]*)$/',$str)
History
first solution preg_match('/^[A-Z][a-z]+\d+$/',$str)
After your edit1: preg_match('/^[a-z]*[A-Z][a-z]*\d+$/',$str)
After your comment about utf8: hum... add at your question the valid language. Example: "José11" is a valid string?
After your edit2 ("jo8hN" is valid): and about number, can repeat? Well I suppose not. "8N" is valid? I suppose yes. preg_match('/^([a-z]*\d+[a-z]*[A-Z][a-z]*|[a-z]*[A-Z][a-z]*\d+[a-z]*)$/',$str) you can add more possibilities with "|" in this regex.
I'm using PHP's PCRE, and there is one bit of the regex I can't seem to do. I have a character class with 5 characters [adjxz] which can appear or not, in any order, after a token (|) on the string. They all can appear, but they can only each appear once. So for example:
*|ad - is valid
*|dxa - is valid
*|da - is valid
*|a - is valid
*|aaj - is *not* valid
*|adjxz - is valid
*|addjxz - is *not* valid
Any idea how I can do it? a simple [adjxz]+, or even [adjxz]{1,5} do not work as they allow repetition. Since the order does not matter also, I can't do /a?d?j?x?z?/, so I'm at a loss.
Perhaps using a lookahead combined with a backreference like this:
\|(?![adjxz]*([adjxz])[adjxz]*\1)[adjxz]{1,5}
demonstration
If you know these characters are followed by something else, e.g. whitespace you can simplify this to:
\|(?!\S*(\S)\S*\1)[adjxz]{1,5}
I think you should break this in 2 steps:
A regex to check for unexpected characters
A simple PHP check for duplicated characters
function strIsValid($str) {
if (!preg_match('/^\*|([adjxz]+)$/', $str, $matches)) {
return false;
}
return strlen($matches[1]) === count(array_unique(str_split($matches[1])));
}
I suggest using reverse logic where you match the unwanted case using this pattern
\|.*?([adjxz])(?=.*\1)
Demo
Trying to create a regex pattern for email address check. That will allow a dot (.) but not if there are more than one next to each other.
Should match:
test.test#test.com
Should not match:
test..test#test.com
Now I know there are thousands of examples on internet for e-mail matching, so please don't post me links with complete solutions, I'm trying to learn here.
Actually the part that interests me the most is just the local part:
test.test that should match and test..test that should not match.
Thanks for helping out.
You may allow any number of [^\.] (any character except a dot) and [^\.])\.[^\.] (a dot enclosed by two non-dots) by using a disjunction (the pipe symbol |) between them and putting the whole thing with * (any number of those) between ^ and $ so that the entire string consists of those. Here's the code:
$s1 = "test.test#test.com";
$s2 = "test..test#test.com";
$pattern = '/^([^\.]|([^\.])\.[^\.])*$/';
echo "$s1: ", preg_match($pattern, $s1),"<p>","$s2: ", preg_match($pattern, $s2);
Yields:
test.test#test.com: 1
test..test#test.com: 0
This seams more logical to me:
/[^.]([\.])[^.]/
And it's simple. The look-ahead & look-behinds are indeed useful because they don't capture values. But in this case the capture group is only around the middle dot.
strpos($input,'..') === false
strpos function is more simple, if `$input' has not '..' your test is success.
To answer the question in the title, I'd update the RegExp by Junuxx and allow dots in the beginning and end of the string:
'/^\.?([^\.]|([^\.]\.))*$/'
which is optional . in the beginning followed by any number of non-. or [non-. followed by .].
^([^.]+\.?)+#$
That should do for the what comes before the #, I'll leave the rest for you.
Note that you should optimise it more to avoid other strange character setups, but this seems sufficient in answering what interests you
Don't forget the ^ and $ like I first did :(
Also forgot to slash the . - silly me
i'm writing my anti spam/badwors filter and i need if is possible,
to match (detect) only words formed by mixed characters like: fr1&nd$ and not friends
is this possible with regex!?
best regards!
Of course it's possible with regex! You're not asking to match nested parentheses! :P
But yes, this is the kind of thing regular expressions were built for. An example:
/\S*[^\w\s]+\S*/
This will match all of the following:
#ss
as$
a$s
#$s
a$$
#s$
#$$
It will not match this:
ass
Which I believe is what you want. How it works:
\S* matches 0 or more non-space characters. [^\w\s]+ matches only the symbols (it will match anything that isn't a word or a space), and matches 1 or more of them (so a symbol character is required.) Then the \S* again matches 0 or more non-space characters (symbols and letters).
If I may be allowed to suggest a better strategy, in Perl you can store a regex in a variable. I don't know if you can do this in PHP, but if you can, you can construct a list of variables like such:
$a = /[aA#]/ # regex that matches all a-like symbols
$b = /[bB]/
$c = /[cC(]/
# etc...
Or:
$regex = array( 'a' => /[aA#]/, 'b' => /[bB]/, 'c' => /[cC(]/, ... );
So that way, you can match "friend" in all its permutations with:
/$f$r$i$e$n$d/
Or:
/$regex['f']$regex['r']$regex['i']$regex['e']$regex['n']$regex['d']/
Granted, the second one looks unnecessarily verbose, but that's PHP for you. I think the second one is probably the best solution, since it stores them all in a hash, rather than all as separate variables, but I admit that the regex it produces is a bit ugly.
It is possible, you will not have very pretty regex rules, but you can match basically any pattern that you can describe using regex. The tricky part is describing it.
I would guess that you would have a bunch of regex rules to detect bad words like so:
To detect fr1&nd$, friends, fr**nd* you can use a regex like:
/fr[1iI*][&eE]nd[s$Sz]/
Doing something like this for each rule will find all the variations of possible characters in the brackets. Pick up a regex guide for more info.
(I'm assuming for a badwords filter you would want friend as well as frie**, you may want to mask the bad word as well as all possible permutations)
Didn't test this thoroughly, but this should do it:
(\w+)*(?<=[^A-Za-z ])
You could build some regular expressions like the following:
\p{L}+[\d\p{S}]+\S*
This will match any sequence of one or more letters (\p{L}+, see Unicode character preferences), one or more digits or symbols ([\d\p{S}]+) and any following non-whitespace characters \S*.
$str = 'fr1&nd$ and not friends';
preg_match('/\p{L}+[\d\p{S}]+\S*/', $str, $match);
var_dump($match);