Complex regular expression to match FOO hyphens and digits - c#

We're trying to create a regular expression, which must match the following strings:
FOO-123123123123
FOO123123123123
FOO-123-123-123-123
It must satisfy the following conditions:
string must begin with FOO
symbols after foo may be only hyphens (optionally) and numbers
there can't be more than one hyphen in a row
the whole length of string can't be more than 50 symbols and less than 6
We've already came up with something like this
^FOO(-{0,1}[\d]+){6,50}$
but it seems like {6,50} sets limit of 50 not for total length of string, but for repeats of this capturing group
(-{0,1}[\d]+)
Can you please advice?

You may use
^(?=.{6,50}$)FOO-?\d+(?:-\d+)*$
See the regex demo.
Details
^ - start of string
(?=.{6,50}$) - the string length should be from 6 to 50 chars
FOO - a FOO substring
-? - an optional -
\d+ - 1+ digits
(?:-\d+)* - 0 or more repetitions of - and then 1+ digits
$ - end of string.
Note: \d may match more than ASCII digits, if you are worried about it compile the regex with RegexOptions.ECMAScript option, or replace \d with [0-9].
Also, ^(?=.{6,50}$)FOO(?:-?\d+)*$ will also work and is shorter, but it is bad parctice to use a single obligatory pattern with other optional patterns inside a quantified group. In this exact case, it is OK, but in other situations, following this logic may lead to catastrophic backtracking.

You can use a lookahead for the specific character checking rules, and a "normal" expression for the overall length.
^FOO(?=(?:-?\d+)+$)[-\d]{3,47}$
The FOO is literal, and it must be the start of the string. The next block is a lookahead ((?=...)). This checks the subsequent string for the rule of no adjacent hyphens, and only digits. A lookahead is non-consuming, so after the lookahead completes, the engine is still looking at the end of "FOO". The last bit of the expression enforces that the only characters which follow "FOO" are hyphens or digits, and that there are a max of between 3 and 47, to account for the max of 6 - 50 (less the length of "FOO").

Related

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

Repeating pattern matching with Regex

I am trying to validate an input with a regular expression. Up until now all my tests fail and as my experience with regex is limited I thought someone might be able to help me out.
Pattern: digit (possibly "," digit) (possibly ;)
A String may not begin with a ; and not end with a ;.
Digits are allowed to stand alone or with
My regEx (not working): ((\d)(,\d)?)(;?) the problem is it does not seem to check until the end of the string. Also the optional parts are giving me headaches.
Update: ^[0-9]+(,[0-9])?(;[0-9]+(,[0-9])?)+$this seems to work better but it does not match the single digit.
OK:
2,3;4,4;3,2
2,3
2
2,3;3;4,3
NOK:
2,3,,,,
2,3asfafafa
;2,3
2,3;;3,4
2,3;3,4;
Your ^[0-9]+(,[0-9])?(;[0-9]+(,[0-9])?)+$ regex matches 1 or more digits, then an optional sequence of , and 1 digit, followed with one or more similar sequences.
You need to match zero or more comma-separated numbers:
^\d+(?:,\d+)?(?:;\d+(?:,\d+)?)*$
^
See the regex demo
Now, tweaking part:
If only single-digit numbers should be matched, use ^\d(?:,\d)?(?:;\d(?:,\d)?)*$
If the comma-separated number pairs can have the second element empty, add ? after each ,\d (if single digit numbers are to be matched) or * (if the numbers can have more than one digit): ^\d(?:,\d?)?(?:;\d(?:,\d?)?)*$ or ^\d+(?:,\d*)?(?:;\d+(?:,\d*)?)*$.

Regular Expression to match a group of alphanumerics followed by a group of spaces, making a fixed total of characters

I'm trying to write a regular expression using C#/.Net that matches 1-4 alphanumerics followed by spaces, followed by 10 digits. The catch is the number of spaces plus the number of alphanumerics must equal 4, and the spaces must follow the alphanumerics, not be interspersed.
I'm at a total loss as to how to do this. I can do ^[A-Za-z\d\s]{1,4}[\d]{10}$, but that lets the spaces fall anywhere in the first four characters. Or I could do ^[A-Za-z\d]{1,4}[\s]{0,3}[\d]{10}$ to keep the spaces together, but that would allow more than a total of four characters before the 10 digit number.
Valid:
A12B1234567890
AB1 1234567890
AB 1234567890
Invalid:
AB1 1234567890 (more than 4 characters before the numbers)
A1B1234567890 (less than 4 characters before the numbers)
A1 B1234567890 (space amidst the first 4 characters instead of at the end)
You can force the check with a look-behind (?<=^[\p{L}\d\s]{4}) that will ensure there are four allowed characters before the 10-digits number:
^[\p{L}\d]{1,4}\s{0,3}(?<=^[\p{L}\d\s]{4})\d{10}$
^^^^^^^^^^^^^^^^^^^^
See demo
If you do not plan to support all Unicode letters, just replace \p{L} with [a-z] and use RegexOptions.IgnoreCase.
Here's the regex you need:
^(?=[A-Za-z0-9 ]{4}\d{10}$)[A-Za-z0-9]{1,4} *\d{10}$
It uses a lookahead (?= ) to test if it's followed by 4 chars, either alnum or space, and then it goes back to where it was (the beggining of string, not consuming any chars).
Once that condition is met, the rest is a expression quite similar to what you were trying ([A-Za-z0-9]{1,4} *\d{10}).
Online tester
I know this is dumb, but must work exactly as required.
^[A-Za-z\d]([A-Za-z\d]{3}|[A-Za-z\d]{2}\s|[A-Za-z\d]\s{2}|\s{3})[\d]{10}$
Not sure what you are looking for, but perhaps:
^(?=.{14}$)[A-Za-z0-9]{1,4} *\d{10}
demo
Try this:
Doesn't allow char/space/char combination and starts with a char:
/\b(?!\w\s{1,2}\w+)\w(\w|\s){3}\d{10}/gm
https://regex101.com/r/fF2tR8/2

Explain the Regex mentioned

Can any one please explain the regex below, this has been used in my application for a very long time even before I joined, and I am very new to regex's.
/^.*(?=.{6,10})(?=.*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z])(?=.*\d.*\d).*$/
As far as I understand
this regex will validate
- for a minimum of 6 chars to a maximum of 10 characters
- will escape the characters like ^ and $
also, my basic need is that I want a regex for a minimum of 6 characters with 1 character being a digit and the other one being a special character.
^.*(?=.{6,10})(?=.*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z])(?=.*\d.*\d).*$
^ is called an "anchor". It basically means that any following text must be immediately after the "start of the input". So ^B would match "B" but not "AB" because in the second "B" is not the first character.
.* matches 0 or more characters - any character except a newline (by default). This is what's known as a greedy quantifier - the regex engine will match ("consume") all of the characters to the end of the input (or the end of the line) and then work backwards for the rest of the expression (it "gives up" characters only when it must). In a regex, once a character is "matched" no other part of the expression can "match" it again (except for zero-width lookarounds, which is coming next).
(?=.{6,10}) is a lookahead anchor and it matches a position in the input. It finds a place in the input where there are 6 to 10 characters following, but it does not "consume" those characters, meaning that the following expressions are free to match them.
(?=.*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z]) is another lookahead anchor. It matches a position in the input where the following text contains four letters ([a-zA-Z] matches one lowercase or uppercase letter), but any number of other characters (including zero characters) may be between them. For example: "++a5b---C#D" would match. Again, being an anchor, it does not actually "consume" the matched characters - it only finds a position in the text where the following characters match the expression.
(?=.*\d.*\d) Another lookahead. This matches a position where two numbers follow (with any number of other characters in between).
.* Already covered this one.
$ This is another kind of anchor that matches the end of the input (or the end of a line - the position just before a newline character). It says that the preceding expression must match characters at the end of the string. When ^ and $ are used together, it means that the entire input must be matched (not just part of it). So /bcd/ would match "abcde", but /^bcd$/ would not match "abcde" because "a" and "e" could not be included in the match.
NOTE
This looks like a password validation regex. If it is, please note that it's broken. The .* at the beginning and end will allow the password to be arbitrarily longer than 10 characters. It could also be rewritten to be a bit shorter. I believe the following will be an acceptable (and slightly more readable) substitute:
^(?=(.*[a-zA-Z]){4})(?=(.*\d){2}).{6,10}$
Thanks to #nhahtdh for pointing out the correct way to implement the character length limit.
Check Cyborgx37's answer for the syntax explanation. I'll do some explanation on the meaning of the regex.
^.*(?=.{6,10})(?=.*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z])(?=.*\d.*\d).*$
The first .* is redundant, since the rest are zero-width assertions that begins with any character ., and .* at the end.
The regex will match minimum 6 characters, due to the assertion (?=.{6,10}). However, there is no upper limit on the number of characters of the string that the regex can match. This is because of the .* at the end (the .* in the front also contributes).
This (?=.*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z]) part asserts that there are at least 4 English alphabet character (uppercase or lowercase). And (?=.*\d.*\d) asserts that there are at least 2 digits (0-9). Since [a-zA-Z] and \d are disjoint sets, these 2 conditions combined makes the (?=.{6,10}) redundant.
The syntax of .*[a-zA-Z].*[a-zA-Z].*[a-zA-Z].*[a-zA-Z] is also needlessly verbose. It can be shorten with the use of repetition: (?:.*[a-zA-Z]){4}.
The following regex is equivalent your original regex. However, I really doubt your current one and this equivalent rewrite of your regex does what you want:
^(?=(?:.*[a-zA-Z]){4})(?=(?:.*\d){2}).*$
More explicit on the length, since clarity is always better. Meaning stay the same:
^(?=(?:.*[a-zA-Z]){4})(?=(?:.*\d){2}).{6,}$
Recap:
Minimum length = 6
No limit on maximum length
At least 4 English alphabet, lowercase or uppercase
At least 2 digits 0-9
REGEXPLANATION
/.../: slashes are often used to represent the area where the regex is defined
^: matches beginning of input string
.: this can match any character
*: matches the previous symbol 0 or more times
.{6,10}: matches .(any character) somewhere between 6 and 10 times
[a-zA-Z]: matches all characters between a and z and between A and Z
\d: matches a digit.
$: matches the end of input.
I think that just about does it for all the symbols in the regex you've posted
For your regex request, here is what you would use:
^(?=.{6,}$)(?=.*?\d)(?=.*?[!##$%&*()+_=?\^-]).*
And here it is unrolled for you:
^ // Anchor the beginning of the string (password).
(?=.{6,}$) // Look ahead: Six or more characters, then the end of the string.
(?=.*?\d) // Look ahead: Anything, then a single digit.
(?=.*?[!##$%&*()+_=?\^-]) // Look ahead: Anything, and a special character.
.* // Passes our look aheads, let's consume the entire string.
As you can see, the special characters have to be explicitly defined as there is not a reserved shorthand notation (like \w, \s, \d) for them. Here are the accepted ones (you can modify as you wish):
!, #, #, $, %, ^, &, *, (, ), -, +, _, =, ?
The key to understanding regex look aheads is to remember that they do not move the position of the parser. Meaning that (?=...) will start looking at the first character after the last pattern match, as will subsequent (?=...) look aheads.

regular expression to match a pattern

I need a regular expression for c# which can match following pattern
abc1abcd
1abcdefg
abcdefg1
basically my expression should have at least one number and min size is 8 char including number. If possible explain the regex also.
I'd probably check with two statements. Just check the length eg
string.Length > 7
and then make sure it this regex can find a match...
[0-9]
You can use a look-ahead assertion to verify the length, and then search forward for a digit, thus:
(?=.{8}).*[0-9]
We look-ahead for 8 characters, and if that is successful, then we actually attempt to match "anything, followed by a digit".
But really, don't do this. Just check the length explicitly. It's much clearer.
Your regular expression pattern should just be: \d+ (match 1 or more numbers). For your example, it's probably best to not determine minimum length using regex since all you care about is that it has at least 1 number and is at least than 8 characters
Regex regEx = new Regex(#"\d+");
isValid = regEx.Match(myString).Success && myString.Length >= 8;
The pattern \d is just the same as [0-9] and the + symbol means at least one of. The # symbol in front of the string is so that it what try to escape \d.
As mentioned by El Ronnoco in the comments, just \d would match your requirement. Knowing about \d+ is useful for more complicated patterns where you want a few numbers in between some strings,etc.
Also: I've just read something that I didn't know. \d matches any character in the Unicode number, decimal digit category which is a lot more than just [0-9]. Something to be aware of if you just want any number. Otherwise El Ronnoco's answer of [0-9] for your pattern is sufficient.

Categories