PHP regex for password validation - php

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

Related

Username may contain lowercase characters and numbers

I want to allow lowercase characters and numbers in username field.
But with following conditions...
Only numbers as username NOT allowed (e.g. only mobile number)
Only lowercase characters allowed (e.g. without any number in username)
Lowercase characters + numbers allowed (e.g. combination of lowercase and numbers)
Minimum length 8 characters required
Maximum length 20 characters allowed
What php regex will do it ?
I tried with following, but it forces lowercase + numbers. Only lowercase username not allowing.
$username_pattern = '/^(?=.*[a-z])(?=.*[a-z])(?=.*\d)[a-z0-9]{8,20}$/';
I want only lowercase and/or lowercase+numbers ( min 8 and max 20 ) in username
Help appreciated.
You can simplify it to not allowing only digits
^(?!\d*$)[a-z0-9]{8,20}$
Explanation
^ Start of string
(?!\d*$) Negative lookahead, assert not only digits till end of string
[a-z0-9]{8,20} Match 8-20 times a char a-z or a digit 0-9
$ End of string
Regex demo | Php demo
$username_pattern = '/^(?!\d*$)[a-z0-9]{8,20}$/';
$userNames = [
"1a3b5678",
"1a3b5678abcd",
"12345678",
"1a3b5678abcddddddddddddddddddddddddddddddd",
"1a3B5678",
"a1"
];
foreach ($userNames as $userName) {
if (preg_match($username_pattern, $userName)) {
echo "Match - $userName" . PHP_EOL;
} else {
echo "No match - $userName" . PHP_EOL;
}
}
Output
Match - 1a3b5678
Match - 1a3b5678abcd
No match - 12345678
No match - 1a3b5678abcddddddddddddddddddddddddddddddd
No match - 1a3B5678
No match - a1

compare two price strings in php with regex

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

preg_match - to allow only one dash

I'm using preg_match and its working to allow; numbers, letters and dash. but i want to limit the dash to 1 only. i tried added {1} before and after the dash but its still allowing more than one. what am i doing wrong?
if (!preg_match("/^[A-Za-z0-9-]+$/", $username)) {
$nameErr = "The username you selected was invalid.<br>Valid characters are dashes (one only), letters and numbers.";
} else {
This is the code that i'm using.
Thanks
Make an extra test for the dash count to keep it simple.
if (!preg_match("/^[A-Za-z0-9\-]+$/", $username) || substr_count($username,'-') > 1) {
$nameErr = "The username you selected was invalid.<br>Valid characters are dashes (one only), letters and numbers.";
}
Since you seem to validate a string that can contain one or zero hyphens in an alphanumeric string, you may use a negative lookahead in your pattern to fail the match if 2 hyphens are found:
"/^(?![^-]*-[^-]*-)[A-Za-z0-9-]+$/D"
^^^^^^^^^^^^^^^^
Pattern details:
^ - start of a string
(?![^-]*-[^-]*-) - fail the match if there are 2 hyphens separated with 0+
chars other than -
[A-Za-z0-9-]+ - 1 or more alphanumeric chars or hyphens
$ - the very end of the string (since /D modifier is used).
See a regex demo (pattern modified to account for a multiline string input).
Note that if you want to disallow - to appear at the start/end of the string, and several consecutive -s, use a more straight-forward pattern:
"/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)?$/D"
where ^[A-Za-z0-9]+ will match 1+ alphanumeric chars at the start of the stirng, and (?:-[A-Za-z0-9]+)?$ will match 1 or 0 occurrences of a - followed with 1+ alphanumeric chars at the end of the string.
$username = "abc-edf-tru-ksk-5-ll-hr-foam-6-inch-queen-anroid-phone-stackoverflow-72-x-70-x-6290321_1";
This below code allow hypens(-) and underscore(_)
if(preg_match('/^[a-zA-Z0-9\-\_]+(-[a-zA-Z0-9\-\_]+)*$/', $username))
{
echo "The username you selected valid characters are hypens,underscores, letters and numbers.";
}
allow only hypen(-)
if(preg_match('/^[a-zA-Z0-9\-]+(-[a-zA-Z0-9\-]+)*$/'), $username))
{
echo "The username you selected valid characters are hypens(only), letters and numbers.";
}
allow only underscore(_)
if(preg_match('/^[a-zA-Z0-9\_]+(-[a-zA-Z0-9\_]+)*$/'), $username))
{
echo "The username you selected valid characters are underscores(only),underscores, letters and numbers.";
}
not allow hypens, underscores and symbols
if(preg_match('/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/'), $username))
{
echo "The username you selected valid characters are letters and numbers.";
}

jQuery regex for username

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.

PHP right search pattern of a char within a fixed length alpha-numerical string

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*

Categories