Regular expression for Password match in PHP and Javascript - javascript

I have built a regular expression for password policy match, but it is not working as expected
/((?=.\d)(?=.[a-z])(?=.[A-Z])(?=.[##\$%!])(?!(.)*\1{2,}).{6,20})/
Password must satisfy below rules
-> must have 1 digit
-> must have 1 upper case letter
-> must have 1 lower case letter
-> must have 1 special character from given list
-> minimum 6 character long
-> maximum 20 character long
-> Not more than 2 identical characters`
So it matches
aDm!n1, Adw1n#
but it must not match below
aaaD!n1, teSt#111
I have searched for this regular expression and found "(?!(.)*\1{2,})" is not working properly
I am not getting why it is not working even though it has lookahead negative assertion.
Thanks in advance

You must need to provide start and end anchors.
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##\$%\!])(?!.*(.).*\1.*\1).{6,20}$
DEMO
To match the strings which isn't contain more than two duplicate characters, you need to use a negative lookahead like (?!.*(.).*\1.*\1) which asserts that the string we are going to match wouldn't contain not more than two duplicate characters.
(?!) Negative lookahead which checks if there isn't
.* Any character zero or more times.
(.) A single character was captured.
.* Any character zero or more times.
\1 Reference to the group index 1. That is, it refers to the character which are already captured by group 1.
.* Any character zero or more times.
\1 Back-referencing to the character which was present inside the group index 1.
Code:
> var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##\$%\!])(?!.*(.).*\1.*\1).{6,20}$/;
undefined
> re.test('aDm!n1')
true
> re.test('Adw1n#')
true
> re.test('tetSt#11')
false

(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##\$%!])(?!.*(.).*\1.*\1).{6,20})
You need this.See demo.
http://regex101.com/r/hQ9xT1/22
Your regex was failing cos
(?!(.)*\1{2,}) will not work as it find consecutive repeated characters and not any character which is three times or more.So use (?!.*(.).*\1.*\1).
var re = /^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##\$%!])(?!.*(.).*\1.*\1).{6,20})$/gm;
var str = 'aaaD!n1\nteSt#111\naDm!n1\nAdw1n#';
var m;
while ((m = re.exec(str)) != null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}

Related

Regex must be in length range and contain letters and numbers

I want to write a regex that will find substrings of length 10-15 where all characters are [A-Z0-9] and it must contain at least 1 letter and one number (spaces are ok but not other special characters). Some examples:
ABABABABAB12345 should match
ABAB1234ABA32 should match
ABA BA BABAB12345 should match
1234567890987 should not match
ABCDEFGHIJK should not match
ABABAB%ABAB12?345 should not match
So far the best two candidates I have come up with are:
(?![A-Z]{10,15}|[0-9]{10,15})[0-9A-Z]{10,15} - this fails because if the string has 10 consecutive numbers/letters it will not match, even though the 15 character string has a mix (e.g ABABABABAB12345).
(?=.*[0-9])(?=.*[A-Z])([A-Z0-9]+){10,15 } - this fails because it will match 15 consecutive letters as long as there is a number later in the string (even though it is outside the match) and vice versa (e.g. 123456789098765 abcde will match 123456789098765).
(I need to do this in python and js)
If each string is on its own line, then you can use start/end anchors to construct the regex:
^(?=.*[0-9])(?=.*[A-Z])(?:\s*[A-Z0-9]\s*){10,15}$
^ - start of line
(?=.*[0-9]) - lookahead, must contain a number
(?=.*[A-Z]) - lookahead, must contain a letter
(?: - start a non-capturing group
\s*[A-Z0-9]\s* Contains a letter or number with optional whitespaace
) - end non-capturing group
{10,15} - Pattern occurs 10 to 15 times
$ - end of line
See a live example here: https://regex101.com/r/eWX2Qo/1
This doesn't account for ABA BA BABAB12345, but this still might help.
Based on what you're trying to match, it looks like you want there to be a mix.
What you can do is two lookaheads. One looking for a in the following 15 characters, and another looking for a letter in the same space. If this matches, then it looks for a group of numbers and letters of length 10 to 15.
(?=.{0,14}\d)(?=.{0,14}[A-Z])[A-Z\d]{10,15}
https://regex101.com/r/qw1Q0S/1
(?=.{0,14}\d) character 1 through 15 has to be a number
(?=.{0,14}[A-Z]) character 1 through 15 has to be a capital letter
[A-Z\d]{10,15} match 10 to 15 letters and numbers if the previous conditions are true
Edit with an improved answer:
To account for the spaces, you can tweak the above concept.
(?=(?:. *+){0,14}\d)(?=(?:. *+){0,14}[A-Z])(?:[A-Z\d] *){10,15}
Above, in the lookahead we were matching .{0,14}. . has been changed to (?:. *+), which is a non capturing group that matches . in addition to 0 or more spaces.
So putting it together:
Lookahead 1:
(?=(?:. *+){0,14}\d)
This matches 0,14 characters that may or may not be followed by spaces. This effectively ignoring spaces. This also uses a possessive quantifier ( *+) when matching spaces to prevent the engine from backtracking when spaces are matched. The pattern would work without the + modifier, but would more than double the steps taken to match on the example.
Lookahead 2:
(?=(?:. *+){0,14}[A-Z])
Same as lookahead 1, but now testing for a capital letter instead of a digit.
If lookahead 1 and lookahead 2 both match, then the engine will be left in a place where our matches can potentially be made.
Actual match:
(?:[A-Z\d] *){10,15}
This matches the capital letters and numbers, but now also 0 or more spaces. The only drawback being that the trailing space will be include in your match, although that's easily handled in post processing.
Edit:
All whitespace (\r, \n, \t and ) can be accounted for by using \s vs .
Depending on the amount of space that exists. the possessive quantifier is necessary to prevent catestrophic backtracking. This modification to the input using possessive quantifiers completes in 22,332 steps, while this one using the same input, but with a regular quantifier, fails match anything due to catastrophic backtracking .
It should be noted that the possessive quantifier *+ is not supported with javascript or python's builtin re module, but it is supported with python's regex module:
>>> import regex
>>> pattern = r'(?=(?:.\s*+){0,14}\d)(?=(?:.\s*+){0,14}[A-Z])(?:[A-Z\d]\s*){10,15}'
>>> regex.search(pattern, 'AAAAAAAAAA\n2')
<regex.Match object; span=(0, 12), match='AAAAAAAAAA\n2'>
>>>
Has the right stuff
function lfunko() {
let a = ["ABABABABAB12345","ABAB1234ABA32","ABA BA BABAB12345","1234567890987","ABCDEFGHIJK","ABABAB%ABAB12?345"];
let o = a.map((s,i) => {
let ll = s.split("").filter(s => s.match(/[A-Z]/)).length;
let ln = s.split("").filter(s => s.match(/[0-9]/)).length;
let ot = s.split("").filter(s => s.match(/[^A-Z0-9]/)).length;
let sum = ll + ln
return (ll > 1 && ln > 1 && sum > 9 && sum < 16 && ot == 0)? `${s} - TRUE`:`${s} - FALSE`;
});
console.log(JSON.stringify(o));
}
Execution log
11:18:20 PM Notice Execution started
11:18:21 PM Info ["ABABABABAB12345 - TRUE","ABAB1234ABA32 - TRUE","ABA BA BABAB12345 - FALSE","1234567890987 - FALSE","ABCDEFGHIJK - FALSE","ABABAB%ABAB12?345 - FALSE"]
11:18:21 PM Notice Execution completed
Your require of [A-Z0-9] does not include spaces so third example should be false.
Should be
ABABABABAB12345 should match
ABAB1234ABA32 should match
ABA BA BABAB12345 should not match has spaces
1234567890987 should not match
ABCDEFGHIJK should not match
ABABAB%ABAB12?345 should not match

React.js RegExp always returns false

I have this code to check if my fields are all good to go. I have my back-end up and working, but I'm struggling to check the regex inside my react method. All I did was created a regex in regex101 before used it on the input pattern, but I wanted to change it to the method. So basically the regex always returns false...
// Then check regex
const regInput = new RegExp(
'^(?:(?:IT|SM)d{2}[A-Z]d{22}|CYd{2}[A-Z]d{23}|NLd{2}[A-Z]{4}d{10}|LVd{2}[A-Z]{4}d{13}|(?:BG|BH|GB|IE)d{2}[A-Z]{4}d{14}|GId{2}[A-Z]{4}d{15}|ROd{2}[A-Z]{4}d{16}|KWd{2}[A-Z]{4}d{22}|MTd{2}[A-Z]{4}d{23}|NOd{13}|(?:DK|FI|GL|FO)d{16}|MKd{17}|(?:AT|EE|KZ|LU|XK)d{18}|(?:BA|HR|LI|CH|CR)d{19}|(?:GE|DE|LT|ME|RS)d{18}|ILd{21}|(?:AD|CZ|ES|MD|SA)d{22}|PTd{23}|(?:BE|IS)d{24}|(?:FR|MR|MC)d{25}|(?:AL|DO|LB|PL)d{26}|(?:AZ|HU)d{27}|(?:GR|MU)d{28})$'
);
if (!regInput.test(this.state.iban)) {
this.setState({
error: true,
errorMsg:
'Sąskaitsssos numeris įvestas klaidingai, bandykite dar kartą',
});
console.log('error');
return;
} else {
console.log('LT597300010145601329');
}
Seems like your regex is the problem. If you are going to have the pattern 2 letters followed by 18 digits, you can try this regex:
^[\w]{2}[\d]{18}$
Here is the regex for an input like: LT597300010145601329
Try:
[a-zA-Z]{2}\d{18}
Note: If you want only uppercase letters, then: [A-Z]{2}\d{18}
According to this link here,
An IBAN, or international bank account number starts with a two-digit country code, then two numbers, followed by several more alphanumeric characters.
You can use the following regex:
^[a-zA-Z]{2}[\d]{2}[a-zA-Z0-9]{14,20}$
In short, this accepts a value with 2 letters(irrespective of the case) followed by 2 digits followed by alphanumeric characters ranging from 14-20 characters (You can change the length constraint if you have more details on the pattern).
Detailed explaination:
Match a single character present in the list below [a-zA-Z]
{2} matches the previous token exactly 2 times
a-z matches a single character in the range between a (index 97) and z (index 122) (case sensitive)
A-Z matches a single character in the range between A (index 65) and
Z (index 90) (case sensitive)
Match a single character present in the list below [\d]
{2} matches the previous token exactly 2 times
\d matches a digit (equivalent to [0-9])
Match a single character present in the list below [a-zA-Z0-9]
{14,20} matches the previous token between 14 and 20 times, as many
times as possible, giving back as needed (greedy)
$ asserts position at the end of a line

How to use RegEx to ignore the first period and match all subsequent periods?

How to use RegEx to ignore the first period and match all subsequent periods?
For example:
1.23 (no match)
1.23.45 (matches the second period)
1.23.45.56 (matches the second and third periods)
I am trying to limit users from entering invalid numbers. So I will be using this RegEx to replace matches with empty strings.
I currently have /[^.0-9]+/ but it is not enough to disallow . after an (optional) initial .
Constrain the number between the start ^ and end anchor $, then specify the number pattern you require. Such as:
/^\d+\.?\d+?$/
Which allows 1 or more numbers, followed by an optional period, then optional numbers.
I suggest using a regex that will match 1+ digits, a period, and then any number of digits and periods capturing these 2 parts into separate groups. Then, inside a replace callback method, remove all periods with an additional replace:
var ss = ['1.23', '1.23.45', '1.23.45.56'];
var rx = /^(\d+\.)([\d.]*)$/;
for (var s of ss) {
var res = s.replace(rx, function($0,$1,$2) {
return $1+$2.replace(/\./g, '');
});
console.log(s, "=>", res);
}
Pattern details:
^ - start of string
(\d+\.) - Group 1 matching 1+ digits and a literal .
([\d.]*) - zero or more chars other than digits and a literal dot
$ - end of string.

JS Regexp for letter that appears at least twice anywhere in the string

/([a-zA-Z]).*?\1/
This regular expression currently returns true on .test() if it finds 1 matching repeating letter. I want it to match atleast 3 or 2 for that matter and return true.
For example, currently it returns true on .test() for strings like;
Trickster, Been, Dekko
But I want it to return true only if there are more than 2 matches so that the following would return true on .test()
CordCord, XoXo, XolXol, PiunPiun
And NOT return true on the strings I mentioned earlier.
You may use a limiting quantifier {2,} after [a-zA-Z] to match 2 or more occurrences of the pattern:
([a-zA-Z]{2,}).*?\1
See the regex demo
Details
([a-zA-Z]{2,}) - Capturing group 1 matching 2 or more ASCII letters
.*? - any 0+ chars other than line breaks, as few as possible (lazy)
\1 - backreference matching the same text as captured in Group 1.
Note that the 2 or more ASCII letters should be captured into 1 group (hence the limiting quantifier is inside the capturing parentheses).
var ss = ['Trickster, Been, Dekko', 'CordCord, XoXo, XolXol, PiunPiun'];
var re = /([a-zA-Z]{2,}).*?\1/;
for (var s of ss) {
console.log(s,"=>",re.test(s));
}
You could specify at least three like this: /([a-zA-Z]){3,}.*?\1/
> /([a-zA-Z]){3,}.*?\1/.test('Been')
<- false
> /([a-zA-Z]){3,}.*?\1/.test('CordCord')
<- true

Regex - string repetition of min length

I want to find any string repetition. I have following code:
let match: Object;
let repetition: ?string;
while ((match = /(.+?)\1+/g.exec(string)) !== null && repetition === null) {
repetition = match[1];
}
It finds 'abc' replication in 'weabcabcjy', but it also finds 'll' in 'all'. I would like to have regex to limit minimal length of replication to 2 characters. It means it compare always minimally 2 characters against others two.
The .+? pattern finds any one or more chars other than linebreak characters, so ll in all will get matched since the first l will be captured into Group 1 and the second one will be matched with \1+.
To only find repetitions of 2+ character chunks you may use a lazy limiting quantifier {2,}?:
/(.{2,}?)\1+/g
See the regex demo.
The (.{2,}?)\1+ pattern will match and capture into Group 1 any two or more, but as few as possible, characters other than linebreak symbols and then 1 or more same consecutive substrings.

Categories

Resources