Regex mask replacement pattern for Phonenumber - c#

I am new to regex
I have phone number regex pattern as (?\d{3})?-? *\d{3}-? *-?\d{4}
I am trying to mask phone number to display only last 4 digits.
I am using a function Regex.Replace("(123) 556-7890 ", "(?\d{3})?-? *\d{3}-? *-?\d{4}", "#")
Would some one help me what would be the replace pattern.
I need out put like for . Input can be XML or JSON
Input
PhoneNumber> (123) 556-7890 PhoneNumber>
Output
PhoneNumber>(XXX) XXX-7890 PhoneNumber>
Input
PhoneNumber> 123 556 7890 PhoneNumber>
Output
PhoneNumber>XXX XXX 7890 PhoneNumber>
Input
PhoneNumber> (123) 556- 7890 PhoneNumber>
Output
PhoneNumber>(XXX) XXX- 7890 PhoneNumber>

You can use a regex to match any digit that is not within the last 4 digits at the end of the string, and replace with an X:
\d(?!\d{0,3}$)
Explantion:
\d - match a digit and...
(?!\d{0,3}$) - fail the match if there is 0 to 3 digits right at the end of the string.
See the regex demo and this C# demo:
var data = new string[] {"(123) 556-7890", "123 556 7890", "(123) 556- 7890"};
foreach (var s in data) {
Console.WriteLine(Regex.Replace(s, #"\d(?!\d{0,3}$)", "X"));
Results:
(XXX) XXX-7890
XXX XXX 7890
(XXX) XXX- 7890
UPDATE showing how to use YOUR regex combined with mine
You just need to use your regex to match the phone numbers in the required format, and use mine to mask the digits inside a match evaluator:
var data = "I have this (123) 556-7890 phone number, followed with 123 556 7890, and (123) 556- 7890.";
var res = Regex.Replace(data, #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}",
x => Regex.Replace(x.Value, #"\d(?!\d{0,3}$)", "X"));
Console.WriteLine(res);
See the IDEONE demo
NOTE that #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}\b" or #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}(?!\d)" might be better patterns to extract phone numbers as the final 4 digits cannot be followed by a word/non-digit character.

If it's always the same number of digits, do you need to do a replace? Surely just taking the last four digits and putting (XXX) XXX- in front of it would achieve the same result?
string masked = "(XXX) XXX-" + input.Substring(input.Length - 4);
Obviously you should still use your original regex to make sure it's a valid phone number first.

Couldn't you simply save the latest 4 digits with \d{4}$ and then mock-up the previous codes? :)

Try this
(\d)([() -]*)(\d)([() -]*)(\d)([() -]*)(\d)([() -]*)(\d)([() -]*)(\d)([() -]*)(\d+)
Substitution
x\2x\4x\6x\8x\10x\12\13
Regex demo
Input
Input
PhoneNumber> (123) 556-7890 PhoneNumber>
Output PhoneNumber>(XXX) XXX-7890 PhoneNumber>
Input
PhoneNumber> 123 556 7890 PhoneNumber>
Output PhoneNumber>XXX XXX 7890 PhoneNumber>
Input
PhoneNumber> (123) 556- 7890 PhoneNumber>
Output PhoneNumber>(XXX) XXX- 7890 PhoneNumber>
Output
Input
PhoneNumber> (xxx) xxx-7890 PhoneNumber>
Output PhoneNumber>(XXX) XXX-7890 PhoneNumber>
Input
PhoneNumber> xxx xxx 7890 PhoneNumber>
Output PhoneNumber>XXX XXX 7890 PhoneNumber>
Input
PhoneNumber> (xxx) xxx- 7890 PhoneNumber>
Output PhoneNumber>(XXX) XXX- 7890 PhoneNumber>

Hey check this function just give the phone number you want to mask as input to the function and it will return you the masked string
function maskPhoneNumber(phoneNumber) {
var regularExpresion = /\(?\d{3}\)?-? *\d{3}-? *-?\d{4}/g, // regular expression to test phone numbers
stringArray,
maskString,
lastString;
// Check if given input matches the phone number pattern
if(regularExpresion.test(phoneNumber)) {
// split phone number to an array of characters to manipulate string
stringArray = phoneNumber.split("");
/*
* splice the array after reversing so that last 4 digits are seperated
* Now stringArray will have last 4 digits and maskString will have remaining characters
*
*/
maskString = stringArray.reverse().splice(4);
// reverse and join the array to get last 4 digits without any change
lastString = stringArray.reverse().join("");
// now replace the remaining characters where digits are present with "X" and then join the array
// concat masked string with last 4 digits to get the required format
phoneNumber = maskString.reverse().join("").replace(/\d/g,"X") + lastString;
}
return phoneNumber;
}

Related

Replace special characters or special characters followed by space

I have this particular string:
Administrationsomkostninger I -2.889 - r0.l l0
I would like to replace these characters:r,l and i with 1.
I use this expression:
([(t|r|l|i|)])
That gives me this string:
Adm1n1s11a11onsomkos1n1nge1 1 -2.889 - 10.1 10
Now i want to replace the all digits that contains a digit followed + a whitespace
so in this case only - 10.1 10 gets converted to -10.110
Try this
string input = "Administrationsomkostninger I -2.889 - r0.l l0";
string pattern = #"(?'spaces'\s){2,}";
string output = Regex.Replace(input, pattern, " ");
​

How do I write regex to validate EIN numbers?

I want to validate that a string follows this format (using regex):
valid: 123456789 //9 digits
valid: 12-1234567 // 2 digits + dash + 7 digits
Here's an example, how I would use it:
var r = new Regex("^[1-9]\d?-\d{7}$");
Console.WriteLine(r.IsMatch("1-2-3"));
I have the regex for the format with dash, but can't figure how to include the non-dash format???
Regex regex = new Regex("^\\d{2}-?\\d{7}$");
This will accept the two formats you want: 2 digits then an optional dash and 7 numbers.
^ \d{9} | \d{2} - \d{7} $
Remove the spaces, they are there for readability.

How to extract contact numbers from long description field?

This is my long input string which contains contact number in between this string like below:
sgsdgsdgs 123-456-7890 sdgsdgs (123) 456-7890 sdgsdgsdg 123 456 7890
sdgsdgsdg 123.456.7890 sdfsdfsdfs +91 (123) 456-7890
Now i want to Extract all input numbers like:
123-456-7890
(123) 456-7890
123 456 7890
123.456.7890
+91 (123) 456-7890
I want to store all this number in array.
This is what i have tried but getting only 2 numbers only:
string pattern = #"^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$";
Regex reg = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
var a = txt.Split();
List < string > list = new List < string > ();
foreach(var item in a) {
if (reg.IsMatch(item)) {
list.Add(item);
}
}
Can anybody help me with this??
Do not use Split for this.
Just go through the matches and get their Groups[0].Value, should be something like this:
foreach (var m in MyRegex.Match(myInput).Matches)
Console.WriteLine(m.Groups[0].Value);
Tested on regexhero:
Regex: \s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?:[ ]*x(\d+))?\s*
Input: sgsdgsdgs 123-456-7890 sdgsdgs (123) 456-7890 sdgsdgsdg 123 456 7890 sdgsdgsdg 123.456.7890 sdfsdfsdfs +91 (123) 456-7890
Output: 5 matches
123-456-7890
(123) 456-7890
123 456 7890
123.456.7890
+91 (123) 456-7890
edit: regexhero didn't like the space in the last group, had to replace it with [ ].
Try to use regex directly on a String, like:
using System.IO;
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
class Program
{
static void Main()
{
Regex regex = new Regex(#"\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*");
Match match = regex.Match("sgsdgsdgs 123-456-7890 sdgsdgs (123) 456-7890 sdgsdgsdg 123 456 7890 sdgsdgsdg 123.456.7890 sdfsdfsdfs +91 (123) 456-7890");
List < string > list = new List < string > ();
while (match.Success)
{
list.Add(match.Value);
match = match.NextMatch();
}
list.ForEach(Console.WriteLine);
}
}
You are getting two numbers because split() by default uses space as delimiter.
Try this tested code.
static void Main(string[] args)
{
string txt = "sgsdgsdgs 123-456-7890 sdgsdgs (123) 456-7890 sdgsdgsdg 123 456 7890 sdgsdgsdg 123.456.7890 sdfsdfsdfs +91 (123) 456-7890";
Regex regex = new Regex(#"\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*");
List<string> list = new List<string>();
foreach (var item in regex.Matches(txt))
{
list.Add(item.ToString());
Console.WriteLine(item);
}
Console.ReadLine();
}

Regex return values from a form result

The result of a web form is being sent to me via text mail and I need to parse all the values from it. I'd like to have a single regex which is capable of returning me a result for a given key.
String Pattern = String.Format("^.*{0}:\s*(?<mail><mailto\:)?(.*)(?(mail)>)\s*$", InputString);
I have these 2 options enabled: RegexOptions.IgnoreCase | RegexOptions.Multiline
Here's a portion of the text which needs to be parsed.
City: Test City
Country: Mycountry
Phone: 212
Fax:
E-Mail: <mailto:mymail#example.com>
This is working well except for the case in which there's no value, e.g. Fax. If I put Fax as InputString the complete next line E-Mail: <mailto:mymail#example.com> is being returned. I want to have either no result or an empty one.
Your issue here is that, even though you're not using RegexOptions.SingleLine and thus . doesn't match \n, the \s character class does match \n.
You can fix this by replacing every instance of \s with [^\S\r\n], i.e. rather than matching "whitespace (including newlines)", match "not (a non-whitespace or newline)".
string pattern = String.Format(
#"^[^\S\r\n]*{0}:[^\S\r\n]*(?<mail><mailto\:)?(.*)(?(mail)>)[^\S\r\n]*$",
"Fax");
However, then you're left with another issue: RegexOptions.Multiline means ^ or $ matches a \n, so you'll be left with a trailing \r on your match if the newlines in your match are \r\n.
To get around this, you can not use RegexOptions.Multiline, but instead replace ^ with (?<=^|\r\n) and $ with (?=$|\r\n), which manually matches a \r\n newline.
Here is a pattern and code which places the items into a dictionary for extraction. If the value is empty, its key is valid in the dictionary but the value contained or returned for that ke is null.
string data = #"City: Test City
Country: Mycountry
Phone: 212
Fax:
E-Mail: <mailto:mymail#example.com>";
string pattern = #"^(?<Key>[^:]+)(?::)(?<Value>.*)";
var resultDictionary =
Regex.Matches(data, pattern, RegexOptions.Multiline)
.OfType<Match>()
.ToDictionary (mt => mt.Groups["Key"].Value, mt => mt.Groups["Value"].Value);
/* resultDictionary is a dictionary with these values:
City Test City
Country Mycountry
Phone 212
Fax
E-Mail <mailto:mymail#example.com>
*/

Basic regex for 16 digit numbers

I currently have a regex that pulls up a 16 digit number from a file e.g.:
Regex:
Regex.Match(l, #"\d{16}")
This would work well for a number as follows:
1234567891234567
Although how could I also include numbers in the regex such as:
1234 5678 9123 4567
and
1234-5678-9123-4567
If all groups are always 4 digit long:
\b\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}\b
to be sure the delimiter is the same between groups:
\b\d{4}(| |-)\d{4}\1\d{4}\1\d{4}\b
If it's always all together or groups of fours, then one way to do this with a single regex is something like:
Regex.Match(l, #"\d{16}|\d{4}[- ]\d{4}[- ]\d{4}[- ]\d{4}")
You could try something like:
^([0-9]{4}[\s-]?){3}([0-9]{4})$
That should do the trick.
Please note:
This also allows
1234-5678 9123 4567
It's not strict on only dashes or only spaces.
Another option is to just use the regex you currently have, and strip all offending characters out of the string before you run the regex:
var input = fileValue.Replace("-",string.Empty).Replace(" ",string.Empty);
Regex.Match(input, #"\d{16}");
Here is a pattern which will get all the numbers and strip out the dashes or spaces. Note it also checks to validate that there is only 16 numbers. The ignore option is so the pattern is commented, it doesn't affect the match processing.
string value = "1234-5678-9123-4567";
string pattern = #"
^ # Beginning of line
( # Place into capture groups for 1 match
(?<Number>\d{4}) # Place into named group capture
(?:[\s-]?) # Allow for a space or dash optional
){4} # Get 4 groups
(?!\d) # 17th number, do not match! abort
$ # End constraint to keep int in 16 digits
";
var result = Regex.Match(value, pattern, RegexOptions.IgnorePatternWhitespace)
.Groups["Number"].Captures
.OfType<Capture>()
.Aggregate (string.Empty, (seed, current) => seed + current);
Console.WriteLine ( result ); // 1234567891234567
// Shows False due to 17 numbers!
Console.WriteLine ( Regex.IsMatch("1234-5678-9123-45678", pattern, RegexOptions.IgnorePatternWhitespace));

Categories