user5911451
user5911451

Reputation:

Masking Phone Number in Java with second character and last four characters printed with regular expressions

I am trying to use regular expression to print the second character and the last four characters of a string.

This is the regular expression I have and its only printing the + and the last four of the string:

s.replaceAll("\\w(?=\\w{4})", "*");

I am using: "+13334445678 " as test dummie data.

I am wanting it to be: +1******5678 I am getting: +*******5678

What am I doing wrong?

Upvotes: 3

Views: 2376

Answers (5)

Amy Brennan-Luna
Amy Brennan-Luna

Reputation: 3

You can use capture groups to perform this task. The regex would match the entire phone number, including the country code. Since you want the masked value to have the country code and last four digits, you'd use capture groups to capture them. Then, you can include them in the replacement. The below link explains in detail what each part of the regex does.

https://regexr.com/4rcq7

String text = "+13334445678 +11234567890";

String regex = "(\\+1)\\d{6}(\\d{4})";
String replacement = "$1******$2";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);

System.out.println(matcher.replaceAll(replacement));

Upvotes: 0

Eugene Khyst
Eugene Khyst

Reputation: 10315

Masking phone number using single regexp may be complicated. After some time, it may take a while to recall what regexp (?<!^\+)[0-9](?=[0-9]{4}) does 😊

More straightforward solution is to use substring method and simple replacement replaceAll("\\d", "*"):

private static String maskPhoneNumber(String tel) {
  if (tel.length() < 6) {
    return tel;
  }
  return tel.substring(0, 2)
      + tel.substring(2, tel.length() - 4).replaceAll("\\d", "*")
      + tel.substring(tel.length() - 4);
}

Examples

maskPhoneNumber("+13334445678"); // +1******5678
maskPhoneNumber("+1-333-444-5678"); // +1-***-***-5678
maskPhoneNumber("+1 (333) 444-5678"); // +1 (***) ***-5678

If you don't want to preserve a phone number format (dashes, spaces, brackets), use add one more replacement (replaceAll("[^\\d]", "")):

tel.substring(0, 2)
  + tel.substring(2, tel.length() - 4)
      .replaceAll("[^\\d]", "")
      .replaceAll("\\d", "*")
  + tel.substring(tel.length() - 4);

Examples

maskPhoneNumber("+13334445678"); // +1******5678
maskPhoneNumber("+1-333-444-5678"); // +1******5678
maskPhoneNumber("+1 (333) 444-5678"); // +1******5678

Such imperative style code is not so elegant as a single regexp but potentially is easier to understand by any developer.

Upvotes: 3

boot-and-bonnet
boot-and-bonnet

Reputation: 761

In case you wanted to preserve any dashes in the format, here is an alternative, using the lambda replace method:

public static void main(String[] args) {
    Pattern phoneObfuscator = Pattern.compile("(?<=\\+\\d)[\\d-]+(?=\\d{4})");
    Pattern digit = Pattern.compile("\\d");

    List<String> numbers = List.of("+13334445678", "+1-123-456-7890");
    for (String number : numbers) { 
        String result = phoneObfuscator.matcher(number).replaceAll(
            m -> digit.matcher(m.group()).replaceAll("*"));
        System.out.printf("%s -> %s%n", number, result);
    }
}

It matches the whole string between the +N and NNNN and replaces each digit with *.

If running a regex multiple times it is usually better to use the compiled version.

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163362

Your pattern \w(?=\w{4}) will also match the digit 1 after the plus sign because it matches a word character and asserts that what is on the right should be 4 word characters.

One option is to add a negative lookbehind (?<!^\+) to assert what is on the left is not the start of the string ^ followed by a plus sign.

Instead of matching a word character, you could match digits [0-9] instead.

(?<!^\+)[0-9](?=[0-9]{4})

Regex demo | Java demo

For example

String s = "+13334445678";
System.out.println(s.replaceAll("(?<!^\\+)[0-9](?=[0-9]{4})", "*"));

Output

+1******5678

If is is not at the start of the string, another option could be to assert what is on the left is not a plus sign that has no non whitespace char before:

(?<!(?<!\S)\+)[0-9](?=[0-9]{4})

Regex demo

Upvotes: 0

karan
karan

Reputation: 8853

If you want to match last 4 digits you can use (.{4})\\s*$. This regex will return last 4 characters from input string irrespective of white spaces at the end.

Upvotes: 0

Related Questions