Regular expression - Phone number ( including +, (,), and length validation - C# - c#

Recently I've to come up with a regular expression for phone number , so as this is already done by many of the devs , i've found a solution related to the same.
And made use of the same in production.
Version#1 is only with numbers:
#"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}"
But then there is an additional requirement: we need to allow special characters like - and ( )
So I modified the regular expression to Version#2 as mentioned below:
#"^([\+]?[0-9]{1}[0-9]{0,2})[\s-]?[\(]?(0?[0-9]\d{0,4}[\)]?[-\s]?)([0-9][\d-\s]{5,7}[\s]?)(x[\d-]{0,4})?$"
Now while validating length of the phone number QA found out that it's accepting more than 16 characters , I've to work again on the regular expression to make it work.
This is where I've found the problem related to Length of the phone number validation using regular expression.
Is there any way to indicate that phone number should accept minimum length as 10 and maximum length as 15 by modifying regular expression ?
Example here could be 123456789 - want to mark this as Invalid phone number as it's having only 9 digits
Example here could be 1234567890123456 - want to mark this as Invalid phone number as it's having only 16 digits
Is there any way to indicate single left parenthesis and single right parenthesis is Invalid inside phone number by modifying regular expression ?
Example here could be 12(34567890 - want to mark this as Invalid phone number , as it's having left parenthesis only
Currently I achieved above things by adding custom attributes to the phone number field. I really want to know , if there's way where we can achieve above things by modifying regular expression itself ?

You may use a regex with a (?=(?:\D*\d){10,15}\D*$) positive lookahead anchored at the start:
^(?=(?:\D*\d){10,15}\D*$)\+?[0-9]{1,3}[\s-]?(?:\(0?[0-9]{1,5}\)|[0-9]{1,5})[-\s]?[0-9][\d\s-]{5,7}\s?(?:x[\d-]{0,4})?$
See the regex demo.
Details:
^ - start of string
(?=(?:\D*\d){10,15}\D*$) - a positive lookahead that makes sure there are 10 to 15 sequences of non-digits followed with 1 digit, and then has 0+ digits up to the end of string
\+? - an optional + symbol
[0-9]{1,3} - 1 to 3 digits
[\s-]? - an optional whitespace or -
(?:\(0?[0-9]{1,5}\)|[0-9]{1,5}) - either of the two alternatives:
\(0?[0-9]{1,5}\) - a (, 1 to 5 digits, )
| - or
[0-9]{1,5} - 1 to 5 digits
[-\s]? - an optional whitespace or -
[0-9] - a digit
[\d\s-]{5,7} - 5 to 7 digits, whitespaces or -
\s? - an optional whitespace
(?:x[\d-]{0,4})? - an optional sequence of:
x - a literal x
[\d-]{0,4} - 0 to 4 digits of -
$ - end of string.

Related

How to validate Regex

Im having a hard time with grouping parts of a Regex. I want to validate a few things in a string that follows this format: I-XXXXXX.XX.XX.XX
Validate that the first set of 6 X's (I-xxxxxx.XX.XX.XX) does not contain characters and its length is no more than 6.
Validate that the third set of X's (I-XXXXXX.XX.xx.XX) does not contain characters and is only 1 or 2.
Now, I have already validation on the last set of XX's to make sure the numbers are 1-8 using
string pattern1 = #"^.+\.(0?[1-8])$";
Match match = Regex.Match(TxtWBS.Text, pattern1);
if (match.Success)
;
else
{ errMessage += "WBS invalid"; errMessage +=
Environment.NewLine; }
I just cant figure out how to target specific parts of the string. Any help would be greatly appreciated and thank you in advance!
You're having some trouble adding new validation to this string because it's very generic. Let's take a look at what you're doing:
^.+\.(0?[1-8])$
This finds the following:
^ the start of the string
.+ everything it can, other than a newline, basically jumping the engine's cursor to the end of your line
\. the last period in the string, because of the greedy quantifier in the .+ that comes before it
0? a zero, if it can
[1-8] a number between 1 and 8
()$ stores the two previous things in a group, and if the end of the string doesn't come after this, it may even backtrace and try the same thing from the second to last period instead, which we know isn't a great strategy.
This ends up matching a lot of weird stuff, like for example the string The number 0.1
Let's try patterning something more specific, if we can:
^I-(\d{6})\.(\d{2})\.(\d{1,2})\.([1-8]{2})$
This will match:
^I- an I and a hyphen at the start of the string
(\d{6}) six digits, which it stores in a capture group
\. a period. By now, if there was any other number of digits than six, the match fails instead of trying to backtrace all over the place.
(\d{2})\. Same thing, but two digits instead of six.
(\d{1,2})\. Same thing, the comma here meaning it can match between one and two digits.
([1-8]{2}) Two digits that are each between 1 and 8.
$ The end of the string.
I hope I understood what exactly you're trying to match here. Let me know if this isn't what you had in mind.
This regex:
^.-[0-9]{6}(\.[1-8]{1,2}){3}$
will validate the following:
The first character can be any character, but is of length 1
It is followed by a dash
The dash is followed by exactly 6 numbers 0 - 9. (If this could be less than 6 characters - for example, between 3 and 6 characters - just replace {6} with {3,6}).
This is followed by 3 groups of characters. Each of this groups are proceeded by a period, are of length 1 or 2, and can be any number 1 - 8.
An example of a valid string is:
I-587954.12.34.56
This is also valid:
I-587954.1.3.5
But this isn't:
I-587954.12.80.356
because the second-to-last group contains a 0, and because the last group is of length 3.
Pleas let me know if I have misunderstood any of the rules.
^I-([0-9]{1,6})\.(.{1,2})\.(0[1-2])\.(.{1,2})$
groups delimited by . (\.) :
([0-9]{1,6}) - 1-6 digits
(.{1,2}) - 1-2 any single character
(0[1-2]) - 01 or 02
(.{1,2}) - 1-2 any single character
you can write and easy test regex on your input data, just google "regex online"

How to mask first 6 and last 4 digits for a credit card number in .net

I'm very new to regex And I'm trying to use a regular expression to turn a credit card number which will be part of a conversation into something like 492900******2222
As it can come from any conversation it might contain string next to it or might have an inconsistent format, so essentially all of the below should be formatted to the example above:
hello my number is492900001111222
number is 4929000011112222ok?
4929 0000 1111 2222
4929-0000-1111-2222
It needs to be a regular expression which extracts the capture group of which I will then be able to use a MatchEvaluator to turn all digits (excluding non digits) which are not the first 6 and last 4 into a *
I've seen many examples here on stack overflow for PHP and JS but none which helps me resolve this issue.
Any guidance will be appreciated
UPDATE
I need to expand upon an existing implementation which uses MatchEvaluator to mask each character that is not the first 6 or last 4 and ideally I dont want to change the MatchEvaluator and just make the masking flexible based on the regular expression, see this for an example https://dotnetfiddle.net/J2LCo0
UPDATE 2
#Matt.G and #CAustin answers do resolve what I asked for but I am hitting another barrier where I cant have it be so strict. The final captured group needs to only take into account the digits and as such maintain the format of the input text.
So for example:
If some types in my card number is 99 9988 8877776666 the output from the evaluation should be 99 9988 ******666666
OR
my card number is 9999-8888-7777-6666 it should output 9999-88**-****-6666.
Is this possible?
Changed the list to include items that are in my unit tests https://dotnetfiddle.net/tU6mxQ
Try Regex: (?<=\d{4}\d{2})\d{2}\d{4}(?=\d{4})|(?<=\d{4}( |-)\d{2})\d{2}\1\d{4}(?=\1\d{4})
Regex Demo
C# Demo
Explanation:
2 alternative regexes
(?<=\d{4}\d{2})\d{2}\d{4}(?=\d{4}) - to handle cardnumbers without any separators (- or <space>)
(?<=\d{4}( |-)\d{2})\d{2}\1\d{4}(?=\1\d{4}) - to handle cardnumbers with separator (- or <space>)
1st Alternative (?<=\d{4}\d{2})\d{2}\d{4}(?=\d{4})
Positive Lookbehind (?<=\d{4}\d{2}) - matches text that has 6 digits immediately behind it
\d{2} matches a digit (equal to [0-9])
{2} Quantifier — Matches exactly 2 times
\d{4} matches a digit (equal to [0-9])
{4} Quantifier — Matches exactly 4 times
Positive Lookahead (?=\d{4}) - matches text that is followed immediately by 4 digits
Assert that the Regex below matches
\d{4} matches a digit (equal to [0-9])
{4} Quantifier — Matches exactly 4 times
2nd Alternative (?<=\d{4}( |-)\d{2})\d{2}\1\d{4}(?=\1\d{4})
Positive Lookbehind (?<=\d{4}( |-)\d{2}) - matches text that has (4 digits followed by a separator followed by 2 digits) immediately behind it
1st Capturing Group ( |-) - get the separator as a capturing group, this is to check the next occurence of the separator using \1
\1 matches the same text as most recently matched by the 1st capturing group (separator, in this case)
Positive Lookahead (?=\1\d{4}) - matches text that is followed by separator and 4 digits
If performance is a concern, here's a pattern that only goes through 94 steps, instead of the other answer's 473, by avoiding lookaround and alternation:
\d{4}[ -]?\d{2}\K\d{2}[ -]?\d{4}
Demo: https://regex101.com/r/0XMluq/4
Edit: In C#'s regex flavor, the following pattern can be used instead, since C# allows variable length lookbehind.
(?<=\d{4}[ -]?\d{2})\d{2}[ -]?\d{4}
Demo

Regex for sales prices

I would like to show prices in the following formats.
100
100,20
1.000,20
11.000,20
111.000,20
1.111.000,20
I have made this regex expression, \d+(\,\d+)? but it only outputs these numbers:
100
100,20
1000,20
11000,20
1111000,20
What I'm missing is the thousand-separator. How can I add this?
I have already read these articles, but still no luck.
MSDN: Regular Expression Language - Quick Reference
DevExpress: Mask Type: Extended Regular Expressions
You may use
\d{1,3}(\.\d{3})*(\R.\d+)?
Here,
\d{1,3} - matches 1 to 3 digits
(\.\d{3})* - matches 0 or more sequences of a literal . followed with exactly 3 digits
(\R.\d+)? - matches an optional (1 or 0) sequences of:
\R. - a decimal separator specified by the System.Globalization.NumberFormatInfo.NumberDecimalSeparator property of the current culture
\d+ - 1+ digits
Unfortunately, there is no digit grouping symbol pattern in DevExpress validation regex, so you might want to hard-code the decimal separator the same way as the "thousand separator" (i.e. \R. -> ,).

Write a regex for number notations

I created this regular expression:
^$|^[1-9]+([\.,]\d{0,2})?$
It should accept:
1
11,00
100,88 (error)
100 (error)
11.00
100.88
Shouldn't accept:
0
-5
0,55
0.55
How can I fix it?
You can enclose the whole pattern with an optional group and use a \d instead of the [1-9] and add a (?!0+) negative lookahead restriction to exclude matching values with leading zeros:
^(?!0+)(?:\d+(?:[.,]\d{0,2})?)?$
^^^^^^^^^ ^^
See the regex demo
If you do not want to match 53.-like values, you need to replace {0,2} with {1,2}.
Pattern details:
^ - start of string
(?!0+) - no zeros at the beginning
(?:\d+(?:[.,]\d{0,2})?)? - optional (one or zero) sequence of:
\d+ - 1 or more digits
(?:[.,]\d{0,2})? - optional (one or zero) sequence of:
[.,] - either a . or ,
\d{0,2} - two, one or zero digits
$ - end of string.
So long as the first character is a digit between 1 and 9, subsequent characters can be any digit. However, your expression excludes subsequent 0's; you need to allow for there to be any number of digits so long as the first character is between 1 and 9:
^$|^[1-9]\d*([\.,]\d{0,2})?$
Pattern Explanation:
^ the beginning of the string
[1-9] any digit except "0"
\d* any digit between 0 and unlimited times
([\.,]\d{0,2})?
(optionally) either "." or "," followed by between zero and 2 digits
$ end of string
See this example for further explanation and unit tests.
From my reading of your question you want the string "(error)" to be a valid suffix. Is that right? If so:
^$|^[1-9]+[0-9]*([\.,]\d{0,2})?( \(error\))?$

c# regex spain mobile phone

what would be a valid regex for these rules:
34 6xx xxx xxx
34 7yx xxx xxx
(note y cannot be 0 (zero))
would this one work?
34(([6][0-9]{8}$)|([7][1-9]{1}[0-9]{7}$))
Your regular expression should work, assuming that you are not expecting it to handle spaces.
You can further optimize your regex by extracting the common suffix of [0-9]{7} from it:
^34(?:6[0-9]|7[1-9])[0-9]{7}$
If you would like to account for optional spaces, insert \s? into your regex in places where you wish to allow space characters to be inserted:
^34\s?(?:6[0-9]|7[1-9])[0-9]\s?[0-9]{3}\s?[0-9]{3}$
If you need to handle this specific format with spaces, you can use
^34 ?(?:6[0-9]{2}|7[1-9][0-9])(?: ?[0-9]{3}){2}$
See RegexStorm demo
REGEX EXPLANATION:
^ - Start of string
34 ? - 34 followed by an optional space
(?:6[0-9]{2}|7[1-9][0-9]) - A group of 2 alternatives: 6 can be followed by any 2 digits, and 7 can be followed only by non-0 and one more digit
(?: ?[0-9]{3}){2} - 2 groups of 3 digits, optionally separated with a space
$ - End of string.

Categories