I'm totally new with regualr expressions and I have to build one with the following requisites:
between 8 and 15 chars
at least 1 alphabetic char (a-z,A-Z)
at least 1 non alphabetic (all the others)
at least 1 CAPITAL letter
at least 1 non-capital letter
maximum of 2 consecutive equal chars (e.g.: 'g' accepted, 'gg' accepted, 'ggg' not)
I tried with this one, but it works only with a maximum of 5 consecutive equal chars (dont understand why). What I'm doing wrong?
var regexp = /^((?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])(.{8,15})(?!.*(.)\1{2}))$/;
EDIT it works with
asdfghjkl1Q
asdfghjkl1QQQ
asdfghjkl1QQQQQ
it not works with
asdfghjkl1QQQQQQ
asdfghjkl1QQQQQq
what i'm trying to obtain is:
WORKING with :
asdfghjkl1Q
asdfghjkl1QQ
asdfghjkl11
NOT WORKING with:
asdfghjkl1QQQ
asdfghjkl1QQq
asdfghjkl111
I think you don't need the outer capturing group so you might omit it.
You could first check for the 8,15 characters until the end of the string $ using a lookahead (?=.{8,15}$)
If all the lookaheads match, then match any character one or more times .+
Try it like this:
^(?=.{8,15}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])(?!.*(.)\1{2}).+$
Related
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.
This question already has answers here:
Regex for password must contain at least eight characters, at least one number and both lower and uppercase letters and special characters
(42 answers)
Closed 3 years ago.
I'm trying to create a regex that allows the 4 main character types (lowercase, uppercase, alphanumeric, and special chars) with a minimum length of 8 and no more than 2 identical characters in a row.
I've tried searching for a potential solution and piecing together different regexes but no such luck! I was able to find this one on Owasp.org
^(?:(?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))(?!.*(.)\1{2,})[A-Za-z0-9!~<>,;:_=?*+#."&§%°()\|\[\]\-\$\^\#\/]{8,32}$
but it uses at least 3 out of the 4 different characters when I need all 4. I tried modifying it to require all 4 but I wasn't getting anywhere. If someone could please help me out I would greatly appreciate it!
Can you try the following?
var strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})");
Explanations
RegEx Description
(?=.*[a-z]) The string must contain at least 1 lowercase alphabetical character
(?=.*[A-Z]) The string must contain at least 1 uppercase alphabetical character
(?=.*[0-9]) The string must contain at least 1 numeric character
(?=.[!##\$%\^&]) The string must contain at least one special character, but we are escaping reserved RegEx characters to avoid conflict
(?=.{8,}) The string must be eight characters or longer
or try with
(?=.{8,100}$)(([a-z0-9])(?!\2))+$ The regex checks for lookahead and rejects if 2 chars are together
var strongerRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,100}$)(([a-z0-9])(?!\2))+$");
reference
I think this might work from you (note: the approach was inspired by the solution to this SO question).
/^(?:([a-z0-9!~<>,;:_=?*+#."&§%°()|[\]$^#/-])(?!\1)){8,32}$/i
The regex basically breaks down like this:
// start the pattern at the beginning of the string
/^
// create a "non-capturing group" to run the check in groups of two
// characters
(?:
// start the capture the first character in the pair
(
// Make sure that it is *ONLY* one of the following:
// - a letter
// - a number
// - one of the following special characters:
// !~<>,;:_=?*+#."&§%°()|[\]$^#/-
[a-z0-9!~<>,;:_=?*+#."&§%°()|[\]$^#/-]
// end the capture the first character in the pair
)
// start a negative lookahead to be sure that the next character
// does not match whatever was captured by the first capture
// group
(?!\1)
// end the negative lookahead
)
// make sure that there are between 8 and 32 valid characters in the value
{8,32}
// end the pattern at the end of the string and make it case-insensitive
// with the "i" flag
$/i
You could use negative lookaheads based on contrast using a negated character class to match 0+ times not any of the listed, then match what is listed.
To match no more than 2 identical characters in a row, you could also use a negative lookahead with a capturing group and a backreference \1 to make sure there are not 3 of the same characters in a row.
^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])(?=[^!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*[!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])(?![a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*([a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])\1\1)[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]{8,}$
^ Start of string
(?=[^a-z]*[a-z]) Assert a-z
(?=[^A-Z]*[A-Z]) Assert A-Z
(?=[^0-9]*[0-9]) Assert 0-9
(?= Assert a char that you would consider special
[^!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*
[!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]
)
(?! Assert not 3 times an identical char from the character class in a row
[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*
([a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])\1\1
)
[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]{8,} Match any of the listed 8 or more times
$ End of string
Regex demo
This is from an exercise on FCC beta and i can not understand how the following code means two consecutive numbers seeing how \D* means NOT 0 or more numbers and \d means number, so how does this accumulate to two numbers in a regexp?
let checkPass = /(?=\w{5,})(?=\D*\d)/;
This does not match two numbers. It doesn't really match anything except an empty string, as there is nothing preceding the lookup.
If you want to match two digits, you can do something like this:
(\d)(\d)
Or if you really want to do a positive lookup with the (?=\D*\d) section, you will have to do something like this:
\d(?=\D*\d)
This will match against the last digit which is followed by a bunch of non-digits and a single digit. A few examples (matched numbers highlighted):
2 hhebuehi3
^
245673
^^^^^
2v jugn45
^ ^
To also capture the second digit, you will have to put brackets around both numbers. Ie:
(\d)(?=\D*(\d))
Here it is in action.
In order to do what your original example wants, ie:
number
5+ \w characters
a non-number character
a number
... you will need to precede your original example with a \d character. This means that your lookups will actually match something which isn't just an empty string:
\d(?=\w{5,})(?=\D*\d)
IMPORTANT EDIT
After playing around a bit more with a JavaScript online console, I have worked out the problem with your original Regex.
This matches a string with 5 or more characters, including at least 1 number. This can match two numbers, but it can also match 1 number, 3 numbers, 12 numbers, etc. In order to match exactly two numbers in a string of 5-or-more characters, you should specify the number of digits you want in the second half of your lookup:
let regex = /(?=\w{5,})(?=\D*\d{2})/;
let string1 = "abcd2";
let regex1 = /(?=\w{5,})(?=\D*\d)/;
console.log("string 1 & regex 1: " + regex1.test(string1));
let regex2 = /(?=\w{5,})(?=\D*\d{2})/;
console.log("string 1 & regex 2: " + regex2.test(string1));
let string2 = "abcd23";
console.log("string 2 & regex 2: " + regex2.test(string2));
My original answer was about Regex in a vacuum and I glossed over the fact that you were using Regex in conjunction with JavaScript, which works a little differently when comparing Regex to a string. I still don't know why your original answer was supposed to match two numbers, but I hope this is a bit more helpful.
?= Positive lookahead
w{5,} matches any word character (equal to [a-zA-Z0-9_])
{5,}. matches between 5 and unlimited
\D* matches any character that\'s not a digit (equal to [^0-9])
* matches between zero and unlimited
\d matches a digit (equal to [0-9])
This expression is global - so tries to match all
You can always check your expression using regex101
I have a numeric code which varies in length from 6-11 digits
which is separated by hyphen after each 3 digits
possible combinations
123-456
123-456-78
123-456-7890
So, here I am trying to convert the user entered code to this format even when entered with spaces and hyphens in the middle.
For Ex:
123 456-7 -> 123-456-7
123456 789 -> 123-456-789
123456 -> 123-456
Valid user input format is 3digits[space or hyphen]3digits[space or hyphen]0to5digits
I tried it like this
code.replace(/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,5})$/,'$1-$2-$3');
But when there are only 6 digits there is a hyphen(-) at the end of the number which is not desired.
123-456-
Could anybody help me with this? Thank you.
The easiest way is probably to just do this with a second replace:
code.replace(/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,4})$/,'$1-$2-$3')
.replace(/-$/, '');
This is chaining a second replace function, which says "replace a - at the end of the string with an empty string". Or in other words, "if the last character of the string is - then delete it.
I find this approach more intuitive than trying to fit this logic all into a replace command, but this is also possible:
code.replace(
/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,4})$/,
'$1-$2' + ($3 == null ? '' : '-') + $3
)
I think it's less obvious at a glance what this code i doing, but the net result is the same. If there was no $3 matched (i.e. your sting only contained 6 digits), then do not include the final - in the replacement.
I believe this will do it for you - replace
^(\d{3})[ -]?()|(\d{3})[ -]?(\d{1,5})
with
$1$3-$2$4
It has two alternations.
^(\d{3})[ -]?() matches start of line and then captures the first group of three digits ($1), then optionally followed by a space or an hyphen. Finally it captures an empty group ($2).
(\d{3})[ -]?(\d{1,5}) matches, and captures ($3), three digits, optionally followed by a space or an hyphen. Then it matches and captures (($4)) the remaining 1-5 digits if they're present.
Since the global flag is set it will make one or two iterations for each sequence of digits. The first will match the first alternation, capturing the first three digits into group 1. Group 2 will be empty.
For the second iteration the first match have matched the first three digits, so this time the second alternation will match and capture the next three digits into group 3 and then the remaining into group 4.
Note! If there only are three digits left after the first match, none of the alternations will match, leaving the last three digits as is.
So at the first iteration group 1 are digits 123. group 2, 3 and 4 are empty. The second iteration group 1 and two are empty, group 3 are the digits 456 and group 4 are digit 7-11.
This gives the first replace $1 = 123- plus nothing, and the second 456-67....
There's no syntax checking in this though. It assumes the digits has been entered as you stated they would.
See it here at regex101.
I am trying to create a regular expression (Java/JavaScript) that matches the following regex, but only when there are fewer than 13 characters total (and a minimum of 4).
(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?) ← originally posted
(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ [A-Z]+)?)
These values should (and do) match:
MED-123
COTA-1224
MED4
COTB-892K777
MED-33 DDD
MED-234J5678
This value matches, but I don't want it to (I want to only match if there are fewer than 12 characters total):
COT-1111J11111111111111
See http://regexr.com/3bs7b http://regexr.com/3bsfv
I have tried grouping my expression and putting {4,12} at the end, but that just makes it look for 4 to 12 instances of the whole expression matching.
I feel like I am missing something simple...thanks in advance for your help!
You can use negative look-ahead:
(?!.{13,})(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?)
Since your expression already make sure that a match starts with COT or MED and there is at least one digit after that, it already guarantees that there are at least 4 characters
I have tried grouping my expression and putting {4,12} at the end, but
that just makes it look for 4 to 12 instances of the whole expression
matching.
This looks for 4 to 12 instances of the whole expression because you didn't add a word boundary \b. Your regex works fine, just add a word boundary and your desired outcome would be achieved. Take a look at this DEMO.
Your regex seems to be very clumsy and looks a little bit hard to read. It is also very limited to certain characters example JK except if you want it to be that way. For a more general pattern, you can check this out
(COT|MED)[AB]?-?[\dJK]{1,8}(\s+D{1,3})?\b
(COT|MED): matches either COT or MED
[AB]?: matches A or B which is optional because of the presence of ?
-?: matches - which is also optional
[\dJK]{1,8}: This matches a number,or J or K with a length of at least one character and a maximum of eight characters.
(\s+D{1,3})?: matches a space or a D at least one time and a maximum of 3 times and this is optional
\b: with respect to your question this seems to be the most important and it creates a boundary for the words that have already been matched. This means that anything exceeding the matched pattern would not be captured.
See the demo here DEMO2
The answer you are looking for is
(?!\S{13})(?:COT|MED)[ABCD]?-?\d{1,4}(?:[JK]+\d*|(?: [A-Z]+)?)
See regex demo
Note that it is almost impossible to check the length of a phrase that is not a whole string or that has spaces inside since boundaries are a bit "blurred". Thus, (?!\S{13}) is a kind of a workaround that just makes sure you do not have a string without whitespace that is 13 characters long or longer.
The regex breakdown:
(?!\S{13}) - Check if the substring that follows does not consist of 13 non-whitespace characters
(?:COT|MED) - Any of the values in the alternation (COTorMED`)
[ABCD]?-? - Optional A, B, C, D and then an optional -
\d{1,4} - 1 to 4 digits
(?:[JK]+\d*|(?: [A-Z]+)?) - a group of 2 alternatives:
[JK]+\d* - J or K, 1 or more times, and then 0 or more digits
(?: [A-Z]+)? - optional space and 1 or more Latin uppercase letters
As this answer suggests, you could solve this this way:
(?=(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?))(?={4 , 12})