JavaScript validation of string using regular expression - javascript

I have to validate string field which start with A-za-z and can contain 0-9_. I have to set limit min 1 char and max 10 char.
Exp=/^([a-zA-Z]) +([0-9._]*)/;

Try this regex:
/^[a-zA-Z][0-9_]{0,9}$/
See demo on regex101.com.

I have to validate string field which start with A-za-z and can contain 0-9_.
I guess A-za-z is a typo, you meant A-Za-z. That is easy, we use ^ for the string start and [A-Za-z] character class for the letter.
I have to set limit min 1 char and max 10 char.
That means, we already have the "min 1 char" requirement fulfilled at Step 1 (one letter at the start). Now, we may have letters, digits, or an underscore, 0 to 9 occurrences - that is, we need to use {0,9} limiting quantifier - up to the end of string (that is, $). A shorthand pattern in JS regex for letters, digits, and underscore is \w.
Use
/^[a-zA-Z]\w{0,9}$/
var re = /^[a-zA-Z]\w{0,9}$/;
var str = 'a123456789';
if (re.test(str)) {
console.log("VALID!")
} else {
console.log("INVALID!")
}

function isValid(string){
if (string.length < 1 || string.length > 10)
return false;
return /^[a-zA-Z][0-9_]*$/.test(string);
}
console.assert(isValid("A"));
console.assert(isValid("a12345"));
console.assert(!isValid(""));
console.assert(!isValid("x123456787212134567"));
console.assert(!isValid("abcdef"));
console.assert(!isValid("012345"));
Don't try to check string length with regex, in most of the cases it is slow and burdensome.

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

limit total number of characters in regex

The string can be a number or a set of numbers, or two groups of numbers separated with "-", but total count of all characters mustn't be more than 6.
Example of valid strings
5
55-33
4444-1
1-4444
666666
Example of invalid strings
-3
6666-
5555-6666
My regex
/^\d+(-?\d+)?$/
But this regex interprets 5555-6666 as a valid string, though its length is more than 6 characters.
I tried following
/^(\d+(-?\d+)?){1,6}$/
but, than I recognized that it interpret enclosed charset as one group, which it expects from 1 to 6.
So how to control total number of chars just with a regexp and requirements described above?
Mehotd 1 :-
Easiest thing you can do it test the length before regex ( i will prefer using this method which checks length and then use regex )
str.length < 7 && /^\d+(-?\d+)?$/.test(str)
Method 2 :-
You can use positive lookahead
^(?=.{0,6}$)\d+(-?\d+)?$
Regex Demo
You can use a positive lookahead pattern to ensure that there can be a maximum of 6 characters:
^(?=.{1,6}$)\d+(?:-\d+)?$
Demo: https://regex101.com/r/kAxuZp/1
Or you can a negative lookahead pattern to ensure that the string does not start with a dash, and another negative lookahead pattern to ensure that the string does not contain two dashes:
^(?!-)(?!.*-.*-)[\d-]{0,5}\d$
Demo: https://regex101.com/r/kAxuZp/3
One option would be to use your current regex pattern and also check the length of the input with dash removed:
var input = "4444-1";
if (/^\d+(-?\d+)?$/.test(input) && input.replace("-", "").length <= 6) {
console.log("MATCH");
}
else {
console.log("NO MATCH");
}
Note that checking the length of the input is only really meaningful after the dash has been removed, because it is only then that we can assert the total number of actual digits.

Validating userName using Regex

The only numbers in the username have to be at the end. There can be zero or more of them at the end.
Username letters can be lowercase and uppercase.
Usernames have to be at least two characters long. A two-letter username can only use alphabet letter characters.
I'm trying with this but I'm stalled. /\d+$\w+/gi
/^[a-z]{2,}\d*$/i is:
^ : the begining
[a-z] : a character (a to z), you can add as many allowed characters as you want
{2,} : at least 2 of them
\d* : 0 or more digits
$ : the end
i : ignore case sensetivity (both lowercases and uppercases are allowed)
Username having characters and digit and min 2 character long
/^[a-zA-Z]{2,}\d*$/i
Test result :
UserNam9 = pass
9username = fail
Userna99 = pass
usernameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee = pass
Us = pass
U = fail
/^[A-z]{2,}[A-z0-9]{0,}$/
/^ // start of line
[A-z]{2,} //alphabet characters 2 or more
[A-z0-9]{0,} //numbers and alphabet
$/ // end of line
You've missed cases when there's a letter in the start, followed by 2 or more numbers.
U99 = fail
d345 = fail
My solution passes these tests, as well:
/^[a-z]{2,}\d*$|(?=\w{3,})^[a-z]{1,}\d+$/i
Using positive lookahead I am making sure that in the second case there are at least 3 alphanumeric characters.
Simplified version of /^[a-z]{2,}\d*$|(?=\w{3,})^[a-z]{1,}\d+$/i:
/^\D(\d{2,}|\D+)\d*$/i
Code explanation:
^ - start of input
\D - first character is a letter
\d{2,} - ends with two or more numbers
| - or
\D+ - has one or more letters next
\d* - and ends with zero or more numbers
$ - end of input
i - ignore case of input
This is my answer, it passed all the tests:
/^[a-z][a-z]+\d*$|^[a-z]\d{2,}$/i
First Part: 2 letters (or more) and zero or more numbers
Or
Second Part: 1 letter and 2 or more numbers

How to limit a string length

I have the following regex:
^[a-zA-Z_][\-_a-zA-Z0-9]*
I need to limit it's length to 39 characters. I tried the following but it didn't work:
^[a-zA-Z_][\-_a-zA-Z0-9]*{,38}
You just need to use a limited quantifier {0,38} and an end of string anchor $:
^[a-zA-Z_][-_a-zA-Z0-9]{0,38}$
^^^^^ ^
The syntax for the limited quantifiers is {min,max} where the max parameter is optional, but the minimum should be present. Without $ you may match 39 first characters in a much longer string.
You do not have to escape a hyphen when it is placed at the beginning of a character class (thus, I suggest removing it).
Also, you can further shorten the regex with an /imodifier:
/^[a-z_][-_a-z0-9]{0,38}$/i
or even
/^[a-z_][-\w]{0,38}$/i
Regarding the question from the comment:
wouldn't also that version work (^[a-zA-Z_][-_a-zA-Z0-9]){0,39}$ with 39 characters limit?
The regex matches
(^[a-zA-Z_][-_a-zA-Z0-9]){0,39} - 0 to 39 sequences of...
^ - start of the string
[a-zA-Z_] - a single character from the specified range
[-_a-zA-Z0-9] - a single character from the specified range
$ - end of string
So, you require a match to include sequences from the start of the string. Note a start of string can be matched only once. As you let the number of such sequences to be 0, you only match either the location at the end of the string or a 2 character string like A-.
Let's see what the regex does with the Word input. It mathces the start of string with ^, then W with [a-zA-Z_], then o with [-_a-zA-Z0-9]. Then the group ends, and that equals to matching the group once. Since we can match more sequences, the regex tries to match r with ^. It fails. So, the next position is retried and failed the same way, because d is not the ^ (start of string). And that way the end of string is matched because there is a 0 occurrences of ^[a-zA-Z_][-_a-zA-Z0-9] and there is an end of string $.
See regex demo
try
^[a-zA-Z_][\-_a-zA-Z0-9]{0,38}$
[0,38] means that number of instances of characters matching [\-_a-zA-Z0-9] could be 0 to 38.
I'm adding this in case you're limiting input field entry.
While not regex, I use this function and it works well (I will add that it's important to let the user know you're limiting the input length from UI/UX point of view):
limitLength: function(element, lengthOf){
var fieldLength = element.value.length;
if(fieldLength <= lengthOf){
return true;
} else {
var str = element.value;
str = str.substring(0, str.length - 1);
element.value = str;
}
}
Usage:
<input type="text" onInput="my.namespace.limitLength(this,39)">

Regular expression for Password match in PHP and 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.
}

Categories

Resources