MVC Regex model validation - regex

I want to have at least 3 numbers in my password.
This validation always fails :
[RegularExpression(#"[\d]{3}", ErrorMessage ="Password must have at least 3 digits")]
[Display(Name = "NewPassword", ResourceType = typeof(ModelResources))]
public string NewPassword { get; set; }
I have also tried with () in the expression. What am I doing wrong?

To require at least three digits, you may use
"^([^0-9]*[0-9]){3}.*$"
or
#"^(?:\D*\d){3}.*$"
or the least effecient regex:
^(.*\d){3}.*$
See regex demo
Note that in .NET \d matches more than just [0-9] digits, it can match Arabic and other digits. The [^0-9] and \D matches any character but a digit.
^ - start of string
([^0-9]*[0-9]){3} - exactly 3 occurrences of 0 or more sequences of
[^0-9]* (or \D*) 0 or more characters other than a digit
[0-9] (or \d) - a digit
.* - 0 or more characters other than a newline
$ - end of string
Please note that using opposite character classes to match 3 digits follows the principle of contrast, which is very effecient compared to dot matching as it involves much less backtracking. You can check for yourself at regex101.com at regex debugger section: it takes 2 backtracking steps for my regex to complete matching and it takes ^(.*\d){3}.*$ ~180 steps to complete matching in the same string.

Related

Regex expression for numbers and leading zeros just with a dot and decimal

I'm trying to find a regex for numeric inputs. We can receive a leading 0 just if we add a dot for adding 1 or 2 decimal numbers. And of course just accept numbers.
These are the scenarios that we can accept:
0.01
1.1
1.02
120.01
We can't accept these values
0023
0100
.01
.12
Which regex is the best option for these cases?
Until now we try we the following regex for accepting just number and dots
[A-Za-z,]
And also we try with the following ones:
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{1})?|(?:,[0-9]{3})*(?:\.[0-9]{1,2})?|(?:\.[0-9]{3})*(?:,[0-9]{1,2})?)$
"/^[-]?[$]\d{1,3}(?:,?\d{3})*\.\d{2}$/"
"/(^(\d{1})\.{0,1}([0-9]){0,2}$)|(^([1-9])\d{0,2}(\,\d{0,3})$)/g"
(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?
And the next one for deleting the leading zeros but it didn't work for 0.10 cases
^0+
If a negative lookahead is supported, you can exclude matches that start with a zero and have no decimal part.
^(?!0\d*$)\d+(?:\.\d{1,2})?$
^ Start of string
(?!0+\d*$) Negative lookahead, assert not a zero followed by optional digits at the right
\d+ Match 1+ digits
(?:\.\d{1,2})? Match an optional decimal part with 1 or 2 digits
$ End of string
Regex demo
I would go with ^(0|[1-9]\d*|(0|[1-9]\d*)\.\d+)$
You can test here: https://regex101.com/r/oNMgR9/1
Explanation
^ means : match the beginning of the string (or line if the m flag is enabled).
$ means : match the end of the string (or line if the m flag is enabled).
(a|b) means match "a" or match "b" so I'll use this to match either "0" alone or any number not starting with a "0". It's the syntax for a logical or.
. alone is used to match any char. So you have to escape it if you want to match the dot character. This is why I wrote 0\. instead of 0..
[ ] is used to list some characters you want to match. It can be a range if you use the - char, so [1-9] means any digit char from "1" to "9".
\d is to match a digit. It's totally equivalent to [0-9].
* means : match the preceding pattern 0 or many times, so \d* means that it will match 0 or many times a digit, so it will match "8" or "465" or "09" but also an empty string "". If you want to match the preceding pattern at least once or many times then you use + instead of *. So \d+ won't match an empty string "" but \d* would match it.
A) Just a number not starting with 0
[1-9]\d* will match any digit from 1 to 9 and then optionnaly followed by other digits. This will match numbers without a decimal point.
B) Just 0
0 alone is a possibility. This is because the case above isn't covering it.
B) A number with decimals
(0|[1-9]\d*)\.\d+ will match either a "0" alone or a number not starting by "0" and then followed by a point and some other digits (which have to be present because we don't want to match "45." without the numbers behind the dot).
Better alternative
The solution from #TheFourthBird is a bit cleaner with the use of a negative lookahead. It's just a bit different to understand. And he read the question completely: You wanted 1 or 2 digits after the decimal. I forgot about that, so, effectively, \d+ should be replaced by \d{1,2} as you don't want more than 2 digits.
You can use
^(?![0.]+$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$
See the regex demo.
Details:
^ - start of string
(?![0.]+$) - fail the match if there are just zeros or dots till end of string
(?:[1-9]\d*|0) - either a non-zero digit followed with any zero or more digits or a zero
(?:\.\d{1,2})? - optionally followed with a sequence of a . and one or two digits
$ - end of string.

Regex to block more than 3 numbers in a string

I am trying to block any strings that contain more than 3 numbers and prevent special characters. I have the special characters part down. I'm just missing the number part.
For example:
"Hello 1234" - Not Allowed
"Hello 123" - Allowed
I've tried the following:
/^[!?., A-Za-z0-9]+$/
/((^[!?., A-Za-z]\d)([0-9]{3}+$))/
/^((\d){2}[a-zA-Z0-9,.!? ])*$/
The last one is the closest I got as it prevents any special characters and any numbers from being entered at all.
I've looked through previous posts, but am coming up short.
Edit for clarification
Essentially I'm trying to find a way to prevent customers from entering PII on a form. No submission should be allowed that contains more than 3 numbers in a string.
Hello1234 - Not allowed
12345 - Not allowed
1111 - not allowed
No where in the comment section when the user enters the string should there be more than 3 numbers in total.
About the patterns that you tried
^[!?., A-Za-z0-9]+$ The pattern matches 1+ times any of the listed, including 1 or more digits
((^[!?., A-Za-z]\d)([0-9]{3}+$)) If {3}+ is supported, the pattern matches a single char from the character class, 1 digit followed by 3 digits
^((\d){2}[a-zA-Z0-9,.!? ])*$ The pattern repeats 0+ times matching 2 digits and 1 of the listed in the character class
You can use a negative lookahead if that is supported to assert not 4 digits in a row.
^(?!.*\d{4})[a-zA-Z0-9,.!? ]+$
regex demo
If there can not be 4 digits in total, but 0-3 occurrences:
^[a-zA-Z,.!? ]*(?:\d[a-zA-Z,.!? ]*){0,3}$
Explanation
^ Start of string
[a-zA-Z,.!? ]* Match 0+ times any of the listed (without a digit)
(?:\d[a-zA-Z,.!? ]*){0,3} Repeat 0 - 3 times matching a single digit followed by optional listed chars (Again without a digit)
$ End of string
regex demo
If you don't want to match an empty string and a lookahead is supported:
^(?!$)[a-zA-Z,.!? ]*(?:\d[a-zA-Z,.!? ]*){0,3}$
See another regex demo
Here is my two cents:
^(?!(.*\d){4})[A-Za-z ,.!?\d]+$
See the online demo
^ - Start string anchor.
(?! - Open a negative lookahead.
( - Open capture group.
.*\d - Match anything other than newline up to a digit.
){4} - Close capture group and match it 4 times.
) - Close negative lookahead.
[A-Za-z ,.!?\d]+ - 1+ Characters from specified class.
$ - End string anchor.
I think it should cover what you described.
Assuming you mean <= 3 digits, this may be a naive one but how about
[ALLOWED_CHARS]*[0-9]?[ALLOWED_CHARS]*[0-9]?[ALLOWED_CHARS]*[0-9][ALLOWED_CHARS]*?
Fill [ALLOWED_CHARS] to whatever you define is not special character and nums.

Regex positive lookahead for "contains 10-14 digits" not working right

I've got a Regular Expression meant to validate that a phone number string is either empty, or contains 10-14 digits in any format. It works for requiring a minimum of 10 but continues to match beyond 14 digits. I've rarely used lookaheads before and am not seeing the problem. Here it is with the intended interpretation in comments:
/// ^ - Beginning of string
/// (?= - Look ahead from current position
/// (?:\D*\d){10,14} - Match 0 or more non-digits followed by a digit, 10-14 times
/// \D*$ - Ending with 0 or more non-digits
/// .* - Allow any string
/// $ - End of string
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
This is being used in an asp.net MVC 5 site with the System.ComponentModel.DataAnnotations.RegularExpressionAttribute so it is in use server side with .NET Regexes and client-side in javascript with jquery validate. How can I get it to stop matching if the string contains more than 14 digits?
The problem with the regular expression
^(?=(?:\D*\d){10,14}\D*|\s*$).*$
is that there is no end-of-line anchor between \D and |. Consider, for example, the string
12345678901234567890
which contains 20 digits. The lookahead will be satisfied because (?:\D*\d){10,14} will match
12345678901234
and then \D* will match zero non-digits. By contrast, the regex
^(?=(?:\D*\d){10,14}\D*$|\s*$).*$
will fail (as it should).
There is, however, no need for a lookahead. One can simplify the earlier expression to
^(?:(?:\D*\d){10,14}\D*)?$
Demo
Making the outer non-capture group optional allows the regex to match empty strings, as required.
There may be a problem with this last regex, as illustrate at the link. Consider the string
\nabc12\nab12c3456d789efg
The first match of (?:\D*\d) will be \nabc1 (as \D matches newlines) and the second match will be 2, the third, \nab1, and so on, for a total of 11 matches, satisfying the requirement that there be 10-14 digits. This undoubtedly is not intended. The solution is change the regex to
^(?:(?:[^\d\n]*\d){10,14}[^\d\n]*)?$
[^\d\n] matches any character other than a digit and a newline.
Demo

Matching exactly 8 digits with 0 or more dashes

I am trying to match an exactly 8 digit phone number that has 0 or more dashes in it. For example, the following should all match:
12345678
123456-78
1234-5678
1-2-3-4-5-6-7-8
If I ignore the dashes, it is rather simple. I can just use:
[\d]{8}
If I want to match a string containing at least 8 characters (digits and dashes) I can use:
[\d-]{8,}
However, here I can't put an upper bound on the number of characters because I don't know how many dashes the number would have.
The only way I thought of would be to use:
[0-9][-]?[0-9][-]?[0-9][-]?[0-9][-]?[0-9][-]?[0-9][-]?[0-9][-]?[0-9]
However, this seems really messy for something that (at least in my mind) seems simple. Is there an easier way to do this?
You can use this regex with optional - after each digit:
^([0-9]-?){8}$
If your regex supports \d then use:
^(\d-?){8}$
RegEx Demo
You should use
^[0-9](-?[0-9]){7}$
^([0-9]-?){8}\b$
See the regex demo #1 and regex demo #2, where \b is used to make sure the last char is a digit (that is a word char).
Details
^ - start of string
[0-9] to match a digit since \d in various regex flavors may match more than just ASCII digits from 0 to 9.
(-?[0-9]){7} - matches 7 sequences of an optional hyphen and a digit, and will not allow trailing hyphen at the end of the string.
([0-9]-?){8} - matches eight occurrences of a digit followed with an optional - char
\b$ - is a trick to make sure the last char is of a word type. Since the pattern can only match a - (a non-word char) or a digit at the end, \b automatically makes sure the last char is a digit.

Regular expression of two digit number where two digits are not same

I am trying to write a regular expression that will match a two digit number where the two digits are not same.
I have used the following expression:
^([0-9])(?!\1)$
However, both the strings "11" and "12" are not matching. I thought "12" would match. Can anyone please tell me where I am going wrong?
You need to allow matching 2 digits. Your regex ^([0-9])(?!\1)$ only allows 1 digit string. Note that a lookahead does not consume characters, it only checks for presence or absence of something after the current position.
Use
^(\d)(?!\1)\d$
^^
See demo
Explanation of the pattern:
^ - start of string
(\d) - match and capture into Group #1 a digit
(?!\1) - make sure the next character is not the same digit as in Group 1
\d - one digit
$ - end of string.