Confusion in two Regex expressions to check at least one number [duplicate] - javascript

I want a regex which returns true when there is at least 5 characters et 2 digits. For that, I use a the lookahead (i. e. (?=...)).
// this one works
let pwRegex = /(?=.{5,})(?=\D*\d{2})/;
let result = pwRegex.test("bana12");
console.log("result", result) // true
// this one won't
pwRegex = /(?=.{5,})(?=\d{2})/;
result = pwRegex.test("bana12");
console.log("result", result) // false
Why we need to add \D* to make it work ?
For me, \d{2} is looser than \D*\d{2} so it should not allow an acceptance of the test?

Your lookaheads only test from the current match position. Since you don't match anything, this means from the start. Since bana12 doesn't start with two digits, \d{2} fails. Its as simple as that ;)
Also, note that having \d{2} means your digits has to be adjacent. Is that your intention?
To simply require 2 digits, that doesn't need to be adjacent, try
/(?=.{5,})(?=\D*\d\D*\d)/

Note that lookaheads are zero-width assertions and when their patterns are matched the regex index stays at the same place where it has been before. The lookaheads in the patterns above are executed at the same locations.
The /(?=.{5,})(?=\d{2})/ pattern will match a location that has any 5 chars other than line break chars immediately to the right of the current location and the first 2 chars in this 5 char substring are digits.
You need to add \D* to let other types of chars before the 2 digits.
See more about that behavior at Lookarounds Stand their Ground.

Related

How can I write the Javascript Regular Expression pattern to handle these conditions

In My exercise, I'm given a task to write a regular expression pattern that validates username input for storage into database.
Usernames can only use alpha-numeric characters.
The only numbers in the username have to be at the end. There can be zero or more of them at the end. Username cannot start with the number.
Username letters can be lowercase and uppercase.
Usernames have to be at least two characters long. A two-character username can only use alphabet letters as characters.
I succeeded to pass all tests except one
A1 is not supposed to match the patern
let userCheck = /^[A-Za-z]+\w\d*$/;
let result = userCheck.test(username);
You can use an alternation after ^[a-z] the first letter to require either [a-z]+ one or more letters followed by \d* any amount of digits | OR \d{2,} two or more digits up to $ end of the string.
let userCheck = /^[a-z](?:[a-z]+\d*|\d{2,})$/i;
See this demo at regex101 - Used with the i-flag (ignore case) to shorten [A-Za-z] to [a-z].
PS: Just updated my answer at some late cup of coffee ☕🌙. Had previously misread the question and removed my answer in meanwhile. I would also have missed the part with e.g. Z97 which I just read at the other answers comments. It's much more of a challenge than at first glance... obviously :)
Edit:
My first answer did not fully solve the task. This regex does:
^([A-Za-z]{2}|[A-Za-z]\w{2,})$
it matches either two characters, or one character followed by at least two characters and/or digits (\w == [A-Za-z0-9]). See the demo here: https://regex101.com/r/sh6UpX/1
First answer (incorrect)
This works for your description:
let userCheck = /^[A-Za-z]{2,}\d*$/;
let result = userCheck.test(username);
Let me explain what went wrong in your regex:
/^[A-Za-z]+\w\d*$/
You correctly match, that the first character is only a letter. The '+' however only ensures, that it is matched at least one time. If you want to match something an exact number of times, you can append '{x}' to your match-case. If you rather want to match a minimum and maximum amount of times, you can append '{min, max}'. In your case, you only have a lower limit (2 times), so the max stays empty and means unlimited times: {2,}
After your [2 - unlimited] letters, you want to have [0 - unlimited] numbers. '\w' also matches letters, so we can just remove it. The end of your regex was correct, as '\d' matches any digit, and '*' quantifies the previous match for the range [0 - unlimited].
I recommend using regex101.com for testing and developing regex patterns. You can test your strings and get very good documentation and explanation about all the tags. I added my regex with some example strings to this link:
https://regex101.com/r/qPmwhG/1
The strings that match will be highlighted, the others stay without highlighting.

Regular Expressions: Positive and Negative Lookahead Solution

I was doing Freecodecamp RegEx challange, which's about:
Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long, do not begin with numbers, and have two consecutive digits
So far the solution I found passed all the tests was:
/^[a-z](?=\w{5,})(?=.*\d{2}\.)/i
However, when I tried
/^[a-z](?=\w{5,})(?=\D*\d{2,}\D*)/i
I failed the test trying to match astr1on11aut (but passed with astr11on1aut). So can someone help me explaining how ?=\D*\d{2,}\D* failed this test?
So can someone help me explaining how (?=\D*\d{2,}\D*) failed this
test?
Using \D matches any char except a digit, so from the start of the string you can not pass single digit to get to the 2 digits.
Explanation
astr1on11aut astr11on1aut
^ ^^
Can not pass 1 before reaching 11 Can match 2 digits first
Note
the expression could be shortened to (?=\D*\d{2}) as it does not matter if there are 2, 3 or more because 2 is the minimum and the \D* after is is optional.
the first expression ^[a-z](?=\w{5,})(?=.*\d{2}\.) can not match the example data because it expects to match a . literally after 2 digits.
Failed for the \d{2,}
Then let's have a look at the regexp match process
/^[a-z](?=\w{5,})
means start with [a-z], the length is at least 6, no problem.
(?=\D*\d{2,}\D*)
means the first letter should be followed by these parts:
[0 or more no-digit][2 or more digits][0 or more no-digits]
and lets have a look at the test case
astr1on11aut
// ^[a-z] match "a"
// length matchs
// [0 or more no-digit]: "str"
// d{2,} failed: only 1 digit
the ?= position lookahead means exact followed by.
The first regular expression is wrong, it should be
/^[a-z](?=\w{5,})(?=.*\d{2}.*)/i
When it comes to lookahead usage in regex, rememeber to anchor them all at the start of the pattern. See Lookarounds (Usually) Want to be Anchored. This will help you avoid a lot of issues when dealing with password regexps.
Now, let's see what requirements you have:
"are greater than 5 characters long" => (?=.{6}) (it requires any 6 chars other than lien break chars immediately to the right of the current location)
"do not begin with numbers" => (?!\d) (no digit allowed immediately to the right)
have two consecutive digits => (?=.*\d{2}) (any two digit chunk of text is required after any 0 or more chars other than line break chars as many as possible, immediately to the right of the current location).
So, what you may use is
^(?!\d)(?=.{6})(?=.*\d{2})
Note the most expensive part is placed at the end of the pattern so that it could fail quicker if the input is non-matching.
See the regex demo.

Match a repeating digit (the same one) exactly two times in Javascript with RegEx

I'm currently trying to match a repeating digit and so far I've got this:
pattern = /(\d){2}/
But when I test this pattern with a number of any length >= 2 it will return true. What I want to find is the following:
When I test the number 12344 it should return true and if the number is 12345 it should return false. But having a number of 12444 should also return false. I want to find the same digit repeated exactly twice.
EDIT: Thanks to anybody proposing a solution!
For this kind of task you have to use lookarounds and backreferences:
(?:^|(.)(?!\1))(\d)\2(?!\2)
Explanation:
(?: // match either...
^ // start of the string
| // or...
(.) // any character
(?!\1) // not followed by the exact same character
)
(\d) // then, match and capture a digit
\2 // and the same digit a 2nd time
(?!\2) // and assert the digit doesn't show up a 3rd time
/(00|11|22|33|44|55|66|77|88|99)/

Regular expression for no more than two repeated letters/digits

I have a requirement to handle a regular expression for no more than two of the same letters/digits in an XSL file.
no space
does not support special chars
support (a-z,A-Z,0-9)
require one of a-z
require one of 0-9
no more than 2 same letter/digits (i.e., BBB will fail, BB is accepted)
What I have so far
(?:[^a-zA-Z0-9]{1,2})
This regex will do it:
^(?!.*([A-Za-z0-9])\1{2})(?=.*[a-z])(?=.*\d)[A-Za-z0-9]+$
Here's the breakdown:
(?!.*([A-Za-z0-9])\1{2}) makes sure that none of the chars repeat more than twice in a row.
(?=.*[a-z]) requires at least one lowercase letter
(?=.*\d) requires at least one digit
[A-Za-z0-9]+ allows only letters and digits
EDIT :
removed an extraneous .* from the negative lookahead
(Partial solution) For matching the same character repeated 3 or more times consecutively, try:
([a-zA-Z0-9])\1{2,}
Sample matches (tested both here and here): AABBAA (no matches), AABBBAAA (matches BBB and AAA), ABABABABABABABA (no matches), ABCCCCCCCCCC (matches CCCCCCCCCC).
Does this one work for you?
/(\b(?:([A-Za-z0-9])(?!\2{2}))+\b)/
Try it out:
var regex = new RegExp(/(\b(?:([A-Za-z0-9])(?!\2{2}))+\b)/)
var tests = ['A1D3E', 'AAAA', 'AABAA', 'abccddeeff', 'abbbc', '1234']
for(test in tests) {
console.log(tests[test] + ' - ' + Boolean(tests[test].match(regex)))
}
Will output:
A1D3E - true
AAAA - false
AABAA - true
abccddeeff - true
abbbc - false
1234 - true
You may do this in 2 regexes:
/^(?=.*[a-z])(?=.*[0-9])[a-z0-9]+$/i This will assure that there is at least 1 digit and 1 letter while accepting only letters and digits (no space or special characters)
/([a-z0-9])\1{2,}/i If this one is matched, then there is a repeated character. Which means you should throw false.
Explanation:
First regex:
^ : match begin of line
(?=.*[a-z]) : check if there is at least one letter
(?=.*[0-9]) : check if there is at least one digit
[a-z0-9]+ : if the checks were true, then match only digits/letters one or more times
$ : match end of line
i : modifier, match case insensitive
Second regex:
([a-z0-9]) : match and group a digit or a letter
\1{2,} : match group 1 two or more times
i : modifier, match case insensitive
In response to a clarification, it seems that a single regular expression isn't strictly required. In that case I suggest you use several regular expressions or functions. My guess is, performance isn't a requirement, since usually these sorts of checks are done in response to user input. User input validation can take 100ms and still appear to be instant, and you can run a lot of code in 100ms.
For example, I personally would do a check for each of your conditions in a separate test. First, check for spaces. Second, check for at least one letter. Next, check for at least one number. Finally, look for any spans of three or more repeated characters.
Your code will be much easier to understand, and it will be much easier to modify the rules later (which, experience has shown, is almost certainly going to happen).
For example:
function do_validation(string) {
return (has_no_space(string) &&
has_no_special_char(string) &&
has_alpha(string) &&
has_digit(string) &&
! (has_repeating(string)))
I personally consider the above to be orders of magnitude easier to read than one complex regular expression. Plus, adding or removing a rule doesn't make you have to reimplement a complex regular expression (and thus, be required to re-test all possible combinations).

Regex split string of numbers at finding of Alpha Characters

OK Regex is one of the most confusing things to me. I'm trying to do this in Javascript. I have a search field that the user will enter a series of characters. Codes are either:
999MC111
or just
999MC
There is ALWAYS 2 Alpha characters. BUT there may be 1-4 characters at the front and sometimes 1-4 characters at the end.
If the code ENDS with the Alpha characters, then I run a certain ajax script. If there are Numbers + 2 letters + numbers....it runs a different ajax script.
My struggle is I know \d is for 2 digits....but it may not always be 2 digits.
So what would my regex code be to split this into an array. or something.
I think correct regex would be (/^([0-9]+)([a-zA-z]+)([0-9]+)$/
But how do i make sure its ONLY 2 alpha characters in middle?
Thanks
You could use the regex /\d$/ to determine if it ends with a decimal.
\d matches a decimal character, and $ matches the end of the string. The / characters enclose the expression.
Try running this in your javascript console, line by line.
var values = ['999MC111', '999MC', '999XYZ111']; // some test values
// does it end in digits?
!!values[0].match(/\d$/); // evaluates to true
!!values[1].match(/\d$/); // evaluates to false
To specify the exact number of tokens you must use brackets {}, so if you know that there are 2 alphabetic tokens you put {2}, if you know that there could be 0-4 digits you put {0,4}
^([0-9]{0,4})([a-zA-z]{2})([0-9]{0,4})$
The above RegEx evaluates as follows:
999MC ---> TRUE
999MC111 --> TRUE
999MAC111 ---> FALSE
MC ---> TRUE
The splitting of the expression into capturing groups is done by means of grouping subexpressions into parentheses
As you can see in the following link:
http://regexr.com?2vfhv
you obtain this:
3 capturing groups:
group 1: ([0-9]{0,4})
group 2: ([a-zA-z]{2})
group 3: ([0-9]{0,4})
The regex /^\d{1,4}[a-zA-Z]{2}\d{0,4}$/ matches a series of 1-4 digits, followed by a series of 2 alpha characters, followed by another series of 0-4 digits.
This regex: /^\d{1,4}[a-zA-Z]{2}$/ matches a series of 1-4 digits, followed only by 2 alpha characters.
Ok so I didnt really care about the middle 2 characters....all that really mattered was the 1st set of numbers and last set of numbers (if any).
So essentially I just needed to deal with digits. So I did this:
var lead = '123mc444'; //For example purposes
var regex = /(\d+)/g;
var result = (lead.match(regex));
var memID = result[0]; //First set of numbers is member id
if(result[1] != undefined) {
var leadID = result[1];
}

Categories

Resources