I want to implement a regex for usernames with the following conditions:
The username will consist of only a-z, A-Z, 0-9 and - (hyphen);
The username shall not consist of ONLY digits or ONLY hyphens but it can have only characters;
The first & last characters shouldn't be hyphens (it can be digits but not entirely digits);
Also, there shouldn't be 2 hyphens back to back;
Minimum number of chars is 5 and max is 25;
So far I have tried this regex:
var filter = /(?=[a-zA-Z0-9-]{5,25}$)^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/;
It achieves conditions 1, 3, 4 and 5 correctly. But it doesn't fully satisfy condition 2. In my regex, it makes sure it doesn't consist entirely of hyphens. But it does allow only digits, which it shouldn't.
Can anyone let me know where I am going wrong or what needs to be done. Explanation of regex will be appreciated.
For maintainability, things like this are usually better written as a series of tests rather than one big test.
var filter = function (username) {
var allDigits = /^[0-9]+$/g,
allHyphens = /^[-]+$/g, //doesn't need a character class, but I find it's more readable
multiHyphens = /[-]+/g,
startsWith = /^[A-Za-z0-9]{1}/,
endsWith = /[A-Za-z0-9]{1}$/
hasInvalidChars = /[^A-Za-z0-9-]/,
meetsReqs = false;
if (username.length >= 5 || username.length <= 25) { //ensure correct length
meetsReqs = !allDigits.test(username);
meetsReqs = meetsReqs && !allHyphens.test(username);
meetsReqs = meetsReqs && !multiHyphens.test(username);
meetsReqs = meetsReqs && !hasInvalidChars.test(username);
meetsReqs = meetsReqs && startsWith.test(username);
meetsReqs = meetsReqs && endsWith.test(username);
}
return meetsReqs;
};
You can add a negative lookahead at the beginning. I also placed the ^ anchor at the beginning of the expression.
^(?![0-9]+$)(?=[a-zA-Z0-9-]{5,25}$)[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$
^^^^^^^^^^^
This prevents against a match of ^[0-9]+$ which is in other words, a string with only numbers.
This seems to work in a quick test on my computer:
^(?![^-]*--+)(?![0-9]+$)[a-zA-Z0-9][-a-zA-Z0-9]{3,23}[a-zA-Z0-9]$
Explanation
^(?![^-]*--+) No double (or more) hyphens
(?![0-9]+$) Digits only forbidden
[a-zA-Z0-9] Starts with a-z A-Z or 0-9
[-a-zA-Z0-9]{3,23} Three to 23 more characters, including hyphens
[a-zA-Z0-9]$ Ends with a-z A-Z or 0-9
So that's 1 + (3 to 23) + 1 characters, ie 5 to 25.
Related
Say we have two price strings in different format:
$s_price = '85.95' or '1500.00'
$r_price = '$ 85.95' or '1,500'
But all these prices are the same and should match.
I have a regex to do that but don't know if this is how we do it:
(\d+)*(,)?\d+(.)?\d*
To retrieve and parse a float from a string in PHP, use the floatval() method.
For the symbols, it depends on wether you always use the same conventions for your currencies (comma for thousands separator and dot for decimals). In that case, you should remove non-digits except dots with the preg_replace() method (the correspondig Regex could be /[^0-9.]/)
<?php
function sanitize($price) {
return floatval(preg_replace('/[^0-9.]/', '', $price));
}
$a1 = '85.95';
$a2 = '1500.00';
$b1 = '$ 85.95';
$b2 = '1,500';
sanitize($a1); // (float) 85.95
sanitize($a2); // (float) 1500
sanitize($b1); // (float) 85.95
sanitize($b2); // (float) 1500
sanitize($a1) === sanitize($b1); // (bool) true
sanitize($a2) === sanitize($b2); // (bool) true
sanitize($a1) <= sanitize($a2); // (bool) true
sanitize($b1) >= sanitize($b2); // (bool) false
Hope it will help !
You have a lot of optional parts in your pattern using ? and * and you could omit the capturing groups if you are not referring to them in the code.
What you might do is match an optional part for the dollar sign followed by 0+ horizontal whitespace chars.
Then match 1+ digits followed by an optional part to match a dot or comma and 1+ digits:
(?<!\S)(?:\$\h*)?\d+(?:[,.]\d+)\b
Explanation
(?<!\S) Assert what is on the left is not a non whitespace char
(?:\$\h*)? Optionally match a dollar sign and 0+ horizontal whitespace chars
\d+(?:[,.]\d+) Match 1+ digits followed by an optional part to match either a dot or comma and 1+ digits
\b word boundary to prevent the digit being part of a larger word
Regex demo | Php demo
you store numbers as integer or float
and to compare you need to use || not or
hope that was helpful
I am trying to find an integer in a string that has the following characteristics:
- Is exactly 8 digits long
- Is between 21000000 and 22000000
- Or between 79000000 and 79999999
I want any number between those ranges to be redacted.
I tried using preg_replace. I'm not sure which pattern to use for this function.
I would suggest this:
preg_replace('/(^|[^0-9]{1})(21[0-9]{6}|22000000|79[0-9]{6})([^0-9]{1}|$)/', '$1 |$2| $3', $str);
// (^|[^0-9]{1}) - set bordering character as non-numeric
// (21[0-9]{6}|22000000|79[0-9]{6}) - match the numbers range you need
// ([^0-9]{1}|$) make sure it doesn't include any other numbers
NB! Make sure you include $1 and $3 in your replace string, otherwise you'll lose chars surrounding the number.
try
<?php
$str ="sdsds21000021dsds";
$int = filter_var($str, FILTER_SANITIZE_NUMBER_INT);
if($int){
$number_of_digits = strlen((string)$int);
if($number_of_digits == 8){
if((($int >= 21000000)&&($int <=22000000))||(($int >= 79000000)&&($int <=79999999))){
echo $int;
} else { // not found }
} else { // not found }
} else { // not found }
hope it helps :)
I've managed to build a regular expression based on what you need.
Hope it helps!
\b21[0-9]{6}\b|\b79[0-9]{6}\b
\b is word boundary
{number} is repetition count
21 is interpreted literally, as 79 is
[0-9] matches exactly one number in 0-9 range
test it here please if you need to tweak it.
https://regex101.com/
I not getting the desired effect from a script. I want the password to contain A-Z, a-z, 0-9, and special chars.
A-Z
a-z
0-9 >= 2
special chars >= 2
string length >= 8
So I want to force the user to use at least 2 digits and at least 2 special chars. Ok my script works but forces me to use the digits or chars back to back. I don't want that. e.g. password testABC55$$ is valid - but i don't want that.
Instead I want test$ABC5#8 to be valid. So basically the digits/special char can be the same or diff -> but must be split up in the string.
PHP CODE:
$uppercase = preg_match('#[A-Z]#', $password);
$lowercase = preg_match('#[a-z]#', $password);
$number = preg_match('#[0-9]#', $password);
$special = preg_match('#[\W]{2,}#', $password);
$length = strlen($password) >= 8;
if(!$uppercase || !$lowercase || !$number || !$special || !$length) {
$errorpw = 'Bad Password';
Using "readable" format (it can be optimized to be shorter), as you are regex newbie >>
^(?=.{8})(?=.*[A-Z])(?=.*[a-z])(?=.*\d.*\d.*\d)(?=.*[^a-zA-Z\d].*[^a-zA-Z\d].*[^a-zA-Z\d])[-+%#a-zA-Z\d]+$
Add your special character set to last [...] in the above regex (I put there for now just -+%#).
Explanation:
^ - beginning of line/string
(?=.{8}) - positive lookahead to ensure we have at least 8 chars
(?=.*[A-Z]) - ...to ensure we have at least one uppercase char
(?=.*[a-z]) - ...to ensure we have at least one lowercase char
(?=.*\d.*\d.*\d - ...to ensure we have at least three digits
(?=.*[^a-zA-Z\d].*[^a-zA-Z\d].*[^a-zA-Z\d])
- ...to ensure we have at least three special chars
(characters other than letters and numbers)
[-+%#a-zA-Z\d]+ - combination of allowed characters
$ - end of line/string
((?=(.*\d){3,})(?=.*[a-z])(?=.*[A-Z])(?=(.*[!##$%^&]){3,}).{8,})
test$ABC5#8 is not valid because you ask more than 2 digits and spec symbols
A-Z
a-z
0-9 > 2
special chars > 2
string length >= 8
For matching length of string including special characters:
$result = preg_match('/^(?=.[a-z])(?=.[A-Z])(?=.\d)(?=.[^A-Za-z\d])[\s\S]{6,16}$/', $string);
Answer explained: https://stackoverflow.com/a/46359397/5466401
Is it possible to validate input depending on whether it only contains a combination of letters, numbers and hyphens (where a hyphen is not repeated twice-in-a-row and does not begins/ends the string)?
Thanks to Validate username as alphanumeric with underscores
I know that the following validates a string based on alphanumeric input with underscores, would it be possible to alter this?
function validate_alphanumeric_underscore($str)
{
return preg_match('/^[a-zA-Z0-9_]+$/',$str);
}
Thank you in advance for your help!
This can be done quite easily with a single regular expression:
/^([a-z0-9]+-)*[a-z0-9]+$/i
This meets all your criteria:
No double hyphens
No beginning/ending hyphens
Works when strlen == 1
Matches:
a
a-a
a-a-a
Doesn't match:
-
a-
-a
a--a
a-a--a
Play with it here.
Assuming a minimum of 2 characters:
This will validate the general format (not starting or ending with a -).
/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i
Then add a simple check for double hyphens using strpos (if it's false, there is no -- in the string, so we want to return true. Otherwise, we want to return false, so that's why the false === is in there):
false === strpos($string, '--');
So, you could do it as:
function validateAlphaNumericUnderscore($string) {
if (0 < preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $string)) {
return false === strpos($string, '--');
}
return false;
}
Now, I'm sure there's a way to do it in a single regex (without needing the additional strpos), but I'm blanking on that now. This is a simple regex, and a simple second string comparison (non regex based).
Hopefully this suits your needs...
Edit: In fact, you could make this more efficient by checking for the -- first (since the string function is cheaper than the regex):
function validateAlphaNumericUnderscore($string) {
if (false === strpos($string, '--')
return 0 < preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $string);
}
return false;
}
ircmaxell's answer uses a regex and a strpos() check, and is an answer I prefer, but here's how I did it with a single regex. Disclaimer: this has vast room for improvement:
function validate_alphanumeric_hyphenated($str)
{
/*
* Match either one or more alphanumeric characters, or a sequence with
* a series of alphanumeric characters without consecutive, leading
* or trailing hyphens.
*
* Is probably unnecessarily long.
*/
return preg_match("/^(?:[a-zA-Z0-9]+|[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?!-))*[a-zA-Z0-9])$/", $str);
}
You could do it with two regexes:
if( !preg_match('/(?:^-|-$|-{2,})/',$str) && preg_match(/^[a-zA-Z0-9_]+$/',$str) ) {
return true;
}
I did a search but I didn't found anything . I'm looking for a pattern that will search in an alpha-numeric string (with the exact length of 7) the letter "P" . This is what I came up with until now , why isn't working ?
$pattern = "/^[\wP]{7}$/";
Well it isn't working because [\wP]{7} (in your regex: /^[\wP]{7}$?/) means find 7 characters that are either a word character OR the letter P. It could find all Ps and it would match, or all word characters and it would match. My quick fix would be to verify the string is 7 letters long using a regex then do a string position to find the "P":
if(preg_match("/^[\w]{7}$/", $target) && strpos($target, "P") != -1) {
// Do stuff
}
Try this:
$pattern = '/^([a-zA-Z0-9]{6})(P{1})$/';
You could condider using strpos and strlen for speed!
\w contains a-z, A-Z, 0-9 and _ so it is not what you want at all.
I'll try with:
if ( preg_match("/^[a-z0-9]*P[a-z0-9]*$/i", $target) && ( strlen($target) == 7 ) ) { ... }
This should match any string that is 7 characters long and contains an uppercase P:
(?=^\w{7}$)\w*P\w*