Greedy regex quantifier not matching password criteria - regex

/(^[a-zA-Z]+-?[a-zA-Z0-9]+){5,15}$/g
regex criteria
match length must be between 6 and 16 characters inclusive
must start with a letter only
must contain letters, numbers and one optional hyphen
must not end with a hyphen
the above regular expression doesnt satisfy all 4 conditions. tried moving the ^ before the group and omitting the + quantifiers but doesnt work

You are setting the limiting quantifier on a group that already has quantified subpatterns, thus, the length restriction won't work.
To set the length restriction, add the (?=.{6,16}$) lookahead after ^ and then feel free to set your consuming pattern.
You may use
/^(?=.{6,16}$)[a-zA-Z][a-zA-Z0-9]*(?:-[a-zA-Z0-9]+)?$/
See the regex demo. Note you should not use g modifier when validating the whole input string against a regex.
Details
^ - start of string
(?=.{6,16}$) - 6 to 16 chars in the string input allowed/required
[a-zA-Z] - a letter as the first char
[a-zA-Z0-9]* - 0+ alphanumeric chars
(?:-[a-zA-Z0-9]+)? - an optional sequence of - and then 1+ alphanumeric chars
$ - end of string.

All you need
^(?i)(?=.{6,16}$)(?!.*-.*-)[a-z][a-z\d-]*\d[a-z\d-]*(?<!-)$
Readable
^
(?i)
(?= .{6,16} $ ) # 6 - 16 chars
(?! .* - .* - ) # Not 2 dashes
[a-z] # Start letter
[a-z\d-]* # Optional letters, digits, dashes
\d # Must be digit
[a-z\d-]* # Optional letters, digits, dashes
(?<! - ) # Not end in dash
$
Well, at least my regex forces a number be present.

Related

Regex match exactly 1 anywhere in string

So I need to match upper and lower case a-z letters, period (.) and # in a string. As a complication the string must have # exactly once anywhere in the string and . at least once anywhere in the string.
abcd#. // match
#ab.cd // match
a#cd#. // no match
abcd# // no match
I've tried to be clever (obviously not very) by doing look ahead but this one seems tricky eg.
(?=[#]){1}[a-zA-Z#]+$
The (?=[#]){1}[a-zA-Z#]+$ pattern matches any substring that starts with # and then has zero or more letters or # up to the end of the string. Look at what it matches.
You need to use
^(?=[^#]*#[^#]*$)(?=[^.]*\.)[a-zA-Z#.]+$
Or, if there must be also one dot (and no more than one) in the string
^(?=[^#]*#[^#]*$)(?=[^.]*\.[^.]*$)[a-zA-Z#.]+$
See the regex demo #1 and the regex demo #2.
Details
^ - start of string
(?=[^#]*#[^#]*$) - requires only one # and no more than one in string - a positive lookahead that requires 0+ chars other than #, a #, and again zero or more chars other than # till the end of string
(?=[^.]*\.) - requires at least one dot - a positive lookahead that requires 0+ chars other than . and then a .
(?=[^.]*\.[^.]*$) - requires only one dot and no more than one in string - a positive lookahead that requires 0+ chars other than ., a ., and again zero or more chars other than . till the end of string
[a-zA-Z#.]+ - one or more ASCII letters, # or .
$ - end of string.
Another option could be using a single lookahead asserting # and match a dot between 2 character classes, or the other way around asserting a dot and matching #
^(?=[^#]*#[^#]*$)[A-Za-z#]*\.[A-Za-z#]*$
Explanation
^ Start of string
(?=[^#]*#[^#]*$) Assert only 1 # char in the string
[A-Za-z#]*\.[A-Za-z#]* Match a dot between optionally repeating character classes each matching 1 out of A-Za-z#
$ End of string
Regex demo
For and . at least once anywhere in the string , you can allow matching a dot in the second character class:
^(?=[^#]*#[^#]*$)[A-Za-z#]*\.[A-Za-z#.]*$
Regex demo
I'm thinking you could just use:
^(?=.*\.)[a-zA-Z.]*#[a-zA-Z.]*$
See the online demo.
^ - Start string ancor.
(?=.*.) - Positive lookahead for any amount of characters up to a literal dot.
[a-zA-Z.]* - Zero or more characters from upper/lowercase letters or a dot.
# - A single #.
[a-zA-Z.]* - Zero or more characters from upper/lowercase letters or a dot.
$ - End string ancor.

Regex match checksum with or without dashes

To match a dash-less checksum I can do something like:
\b[0-9a-z]{32}\b
However, I'm seeing some checksums that also have dashes, such as:
d3bd55bf-062f-473b-9417-935f62c4c98a
While this is probably a fixed size, 8, then 4, then 4, then 4, then 12, I was wondering if I could do a regex where the number of non-dash digits adds up to 32. I think the answer is no, but hopefully some regex wizard can come up with something.
Here is a starting point for some sample inputs: https://regex101.com/r/K0IMKe/1.
You can use
\b[0-9a-z](?:-?[0-9a-z]){31}\b
See the regex demo.
It matches
\b - a word boundary
[0-9a-z] - a digit or a lowercase ASCII letter
(?:-?[0-9a-z]){31} - thirty-one repetitions of an optional - followed with a single digit or a lowercase ASCII letter
\b - a word boundary.
If you do not mind having a trailing - if there is a word char after it, at the end of a match, you may also use
\b(?:[0-9a-z]-?){32}\b
See this regex demo. Here, (?:[0-9a-z]-?){32} will match thirty-two repetitions of a digit or lowercase ASCII letter followed with an optional hyphen.
If there can be multiple dashes, you can assert 32 to 36 chars using a positive lookahead.
^(?=[a-z0-9-]{32,36}$)[a-z0-9]+(?:-[a-z0-9]+)*$
^ Start of string
(?=[a-z0-9-]{32,36}$) Positive lookahead, assert what is at the right is 32 - 36 repetitions of the listed characters
[a-z0-9]+ Match 1+ times any of the listed
(?: Non capture group
-[a-z0-9]+ Match a - followed by 1+ times any of the listed (the string can not end with a hyphen)
)* Close the group and match 0+ times to also match the string without dashes
$ End of string
Regex demo
If you want to limit the amount of dashes to 0 -4 times, you can change the quantifier * to {0,4}+
^(?=[a-z0-9-]{32,36}$)[a-z0-9]+(?:-[a-z0-9]+){0,4}+$
Regex demo

How can I allow one space in a regular expression

The following Regex checks for a number which starts with 6, 8 or 9 and has to be exactly 8 digits long.
/^(6|8|9)\d{7}$/
Now I want to accept one space in between digits as well, but don't know where to start.
For example both 61234567 and 6123 4567 should be allowed, but only the first one passes my current regex.
Can you help me create it?
You may use
^(?!.*(?:\s\d+){2})[689](?:\s?\d){7}$
See the regex demo
Details
^ - start of string
(?!.*(?:\s\d+){2}) - a negative lookahead that fails the match if, after any 0+ chars other than line break chars, as many as possible occurrences, there are two occurrences of a whitespaces followed with 1+ digits
[689] - 6, 7 or 9
(?:\s?\d){7} - seven occurrences of an optional whitespace followed with a single digit
$ - end of string.
To allow leadign/trailing whitespace, add \s? (1 or 0) or \s* (0 or more) right after ^ and before $.
To allow a single 1+ more whitespace chunk in the digit string, use
^(?!.*(?:\s+\d+){2})[689](?:\s*\d){7}$
See this regex demo.
You could use the regular expression
/^[689](?:\d{7}|(?=.{8}$)\d* \d+)$/
demo
We can make this self-documenting by writing it in free-spacing mode:
/
^ # match beginning of line
[689] # match '6', '8' or '9'
(?: # begin non-capture group
\d{7} # match 7 digits
| # or
(?=.{8}$) # require the remainder of the line to have 8 chars
\d*\ \d+ # match 0+ digits, a space, 1+ digits
) # end non-capture group
$ # match end of line
/x # free-spacing regex definition mode

checking if one expression contains the next expression in regex

I want my regex to allow alphanumeric characters, "/_-" and white spaces in between but it must always have at least one alphanumeric character.
my validation goes like this,
/^([A-Za-z0-9/-]+[A-Za-z0-9/-\s]*[A-Za-z0-9/_-]+)$/
It should accept **ABC_1-2-3 but it must not allow 123 or -_/ alone
Can somebody help me please.
The below given regex will capture strings with alpha-numeric characters with optional white space, hyphen and underscore in it. Try it.
([*A-Za-z]+(\s+)?([\d\-_]+)?)
Your regex is almost right, you need to add 2 positive lookaheads at the start to require at least 1 letter and at least 1 digit:
/^(?=.*[a-z])(?=.*\d)[a-z0-9\/_-][a-z0-9\/_\s-]*[a-z0-9\/_-]$/i
See the regex demo (in the demo, \s is replaced with a space since the demo is multiline).
Details:
^ - start of string
(?=.*[a-z]) - after any 0+ chars other than line break chars, there must be at least 1 letter (replace .* with [^a-z]* for better performance)
(?=.*\d) - after any 0+ chars other than line break chars, there must be at least 1 digit (replace.with\D` for better performance)
[a-z0-9\/_-] - a letter, digit, /, _ or -
[a-z0-9\/_\s-]* - 0+ letters, digits, /, whitespaces, _ or -
[a-z0-9\/_-] - a letter, digit, /, _ or -
$ - end of string.
The i modifier makes the pattern case insensitive.

Regex - minimum and maximum of each symbol type

I need to check if the string contains from 0 to 3 spaces and 16 digits. How can I do this ? All that I come up with is only for checking the sum
^[0-9- ]{16,19}$
You actually should use
^(?=(?:[^ ]* ){0,3}[^ ]*$)(?=(?:[^0-9]*[0-9]){16}[^0-9]*$)[0-9- ]+$
See the regex demo at regex101.com.
Alternatively, the first space checking positive lookahead may be replaced with a negative one with reverse logic:
^(?!(?:[^ ]* ){4})(?=(?:[^0-9]*[0-9]){16}[^0-9]*$)[0-9- ]+$
See another demo
Both the regexps are written with the principle of contrast in mind, so as to fail the regex quicker if the lookahead pattern does not match.
Details:
^ - start of string
(?!(?:[^ ]* ){4}) - a negative lookahead failing the match if there are 4 sequences immediately to the right of the current location, of:
[^ ]* - 0+ chars other than a space
- a space
(?=(?:[^0-9]*[0-9]){16}[^0-9]*$) - a positive lookahead requiring that the whole string should contain 16 sequences of 0+ non-digits ([^0-9]*) followed with 1 digit, and then 0+ chars other than a digit up to the end of the string
[0-9- ]+ - matches 1+ chars that are either digits, - or spaces
$ - end of string.
You can use this regex based on lookaheads:
^[0-9](?!(?:[0-9]* ){4})(?=(?: *[0-9]){15}$)[0-9- ]+[0-9]$
RegEx Demo
^[0-9] and [0-9]$ ensures we have only digits at start and end.
(?!(?:[0-9]* ){4}) is negative lookahead to disallow 4 spaces (thus allowing 0 to 3 whitespaces)
(?=(?: *[0-9]){16} *$) is positive lookahead to allow exactly 16 digits in the input surrounded by optional spaces.