Regex to replace all characters except first 3

Viewed 64

I have a requirement to replace the following strings in the given format through the regex. Any help would be appreciated.

  1. johnsmith@gmail.com => johxxxxx@xxxx.xxx (All the characters should be replaced with x other than the first three, @, and dot (.)).
  2. John Smith => Johx Smixx (All the characters should be replaced with x other than the first three characters from each letter)
  3. 9876543210 => 987xxx3210 (All the characters should be replaced with x other than the first three and the last four)

Thanks in advance.

2 Answers
php > echo preg_replace('/(?<=...)[^@.]/', 'x', 'johnsmith@gmail.com');
johxxxxxx@xxxxx.xxx

https://regex101.com/r/ASq1N2/1

2.

php > echo preg_replace('/(?<=\S{3})\S/', 'x', 'John Smith');
Johx Smixx

https://regex101.com/r/zqhwSg/1

3.

php > echo preg_replace('/(?<=.{3}).(?=.{4})/', 'x', '9876543210');
987xxx3210

https://regex101.com/r/ppmBUm/1


ad 1.
Approach:
a) I want to replace all individual characters that are not @ or .
b) I want to make sure the character to be replaced is at least the 4th character in the string.
That means it has to have at least 3 characters left of it

a) To match a character I use the [] "character class" operator.
In it I can specify what characters to match. Or which characters not to match, if I start with ^. That's why [^@.] will match a single character that is not one of @ or ..
(Note: ^ has a different meaning OUTside of []).

b) we can look to the left by using a "look-behind" (?=) expression. After the = I have to specify what I want to match. I want to match any 3 characters, so ... will do. (as . outside of character classes matches any character)
(As alternative solution I could also use .{3} like I did in answer 3.,
which means "match any character, do that exactly 3 times")
Resulting in (?=...)

Now let's plug it together.
First look left to make sure the character that we will match has at least 3 others left of it. Then let's match the character.
(?<=...)[^@.]

In case you must use regex, this is how you do it for the email thing..

<?php
$regex = "/(\w{3})([^@]+)@([^\.]+)\.(.*)/";

$email = "johnsmith@gmail.com";

preg_match_all($regex, $email, $matches);


if(count($matches) == 5){
    $email = $matches[0][0];
    $email = str_replace($matches[2][0], str_repeat("*", strlen($matches[2][0])), $email);
    $email = str_replace($matches[3][0], str_repeat("*", strlen($matches[3][0])), $email);
    $email = str_replace($matches[4][0], str_repeat("*", strlen($matches[4][0])), $email);
    
    echo $email;
}

?>

For the name part you can do like this.. (regex will be kind complex)

<?php
$name = "John Smith";
$nameParts = array_map(function($element){
    return substr($element, 0, 3) . str_repeat("*", strlen($element) - 3);
}, explode(" ", $name));
$maskedName = implode(" ", $nameParts);

echo $maskedName;
?>

For the last one you can apply same kind of logic.

Related