Java中的电子邮件地址屏蔽

27

我试图用 "*" 掩盖电子邮件地址,但我不擅长正则表达式。

input : nileshxyzae@gmail.com
output : nil********@gmail.com

我的代码是

String maskedEmail = email.replaceAll("(?<=.{3}).(?=[^@]*?.@)", "*");
但是它给我输出nil*******e@gmail.com,我不知道出了什么问题。为什么最后一个字符没有转换? 还有人能解释一下所有这些正则表达式的含义吗?
还有人能解释一下所有这些正则表达式的含义吗?

9
这是你的真实电子邮件地址吗?如果是,你可能需要考虑更改它... - nitzanms
7个回答

41

您的正向预查表达式(?=[^@]*?.@)要求在@前至少有1个字符存在(请注意@之前的点号)。

如果您将其去除,则会替换所有预期的符号:

(?<=.{3}).(?=[^@]*?@)

这里是正则表达式演示(将其替换为*)。

然而,这个正则表达式不适合此任务。您需要一个正则表达式,它将匹配第一个@之后的前3个字符之后的每个字符:

(^[^@]{3}|(?!^)\G)[^@]

请看另一个正则表达式演示,将其替换为$1*。在这里,[^@]匹配任何不是@的字符,因此我们不会匹配像abc@example.com这样的地址。仅掩盖用户名部分具有4个或更多字符的电子邮件。

请看IDEONE 演示

String s = "nileshkemse@gmail.com";
System.out.println(s.replaceAll("(^[^@]{3}|(?!^)\\G)[^@]", "$1*"));

第二个正则表达式可以简化为(^[^@]{3}|(?!^)\G)[^@] - nhahtdh
@nhahtdh: 或 (^[^@]{3}|(?!^)\G)[^@](?=[^@]*@)。有趣的是,去掉前瞻后,完成匹配所需的步骤数量增加了。 - Wiktor Stribiżew
你需要在调试器中勾选“禁用内部引擎优化”复选框。这样做后,失败案例和没有前瞻的案例步骤数相同,而成功案例中没有前瞻的步骤更少。在Java中,没有针对具有前瞻的情况进行优化。 - nhahtdh
谢谢您提醒如何更好地使用regex101来调试Java正则表达式的提示 :) 或许可以使用所有格量词来克服这个缺点,但我同意在这里删除它是一个有效的方法。 - Wiktor Stribiżew
1
@MateenChaudhry 使用 (?<=.{3}).(?=[^@]+@),请参见 演示 - Wiktor Stribiżew
显示剩余4条评论

19

如果你不擅长正则表达式,就不要使用它们 :) 我不知道你是否听说过这句话:

有些人遇到问题时会想:“我知道了,我将使用正则表达式。” 现在他们有两个问题了。

(来源)

也许你可以在这里得到一个可工作的正则表达式,但是今天你能理解它吗?明天?六个月后呢?你的同事们呢?

一个简单的替代方法是使用 StringBuilder,我认为这样更容易理解正在发生什么:

StringBuilder sb = new StringBuilder(email);
for (int i = 3; i < sb.length() && sb.charAt(i) != '@'; ++i) {
  sb.setCharAt(i, '*');
}
email = sb.toString();

从第三个字符开始,用一个 * 代替这些字符,直到你到达字符串的结尾或者 @ 符号。

(甚至无需使用 StringBuilder:您可以直接操作 email.toCharArray() 中的元素,然后在最后构造一个新的字符串)。

当然,对于本地部分少于3个字符的电子邮件地址,这种方法是不正确的——它会掩盖域名。


10
您的前瞻功能有点复杂。请尝试使用以下代码:

public static void main(String... args) throws Exception {
    String s = "nileshkemse@gmail.com";
    s= s.replaceAll("(?<=.{3}).(?=.*@)", "*");
    System.out.println(s);
}

输出:

nil********@gmail.com

1
为什么要使用\w而不是简单的.?这会导致"foo.bar@gmail.com" -> "foobar@gmail.com",而不是"foo***@gmail.com"。 - xehpuk
@xehpuk - 是的。我之前没有考虑到那种情况。现在已经改好我的代码了。谢谢。 - TheLostMind

4
//In Kotlin

val email = "nileshkemse@gmail.com"
val maskedEmail = email.replace(Regex("(?<=.{3}).(?=.*@)"), "*")

6
虽然你的代码可能提供了问题的答案,请添加一些上下文,以便其他人了解它的作用和存在意义。 - Theo
1
感谢您的建议。在Java中,我们有replaceAll方法,但在Kotlin中却没有。这是为了帮助学习Kotlin的用户而发布的信息。 - Ajay Prajapati

3

我喜欢这个方法,因为我只想隐藏四个字符,并且如果电子邮件地址太短,它还会自动减少隐藏字符到两个:

public static String maskEmailAddress(final String email) {
    final String mask = "*****";
    final int at = email.indexOf("@");
    if (at > 2) {
        final int maskLen = Math.min(Math.max(at / 2, 2), 4);
        final int start = (at - maskLen) / 2;
        return email.substring(0, start) + mask.substring(0, maskLen) + email.substring(start + maskLen);
    }
    return email;
}

示例输出:
my.email@gmail.com    >    my****il@gmail.com
info@mail.com         >    i**o@mail.com

如何以相同的方式掩盖Gmail? - Vanya Rachel
@VanyaRachel - 你找到怎么做了吗? - Sam Berchmans
你可以将if块制作成一个函数,并在这次使用中使用:domain = email.substring(0, at + 1),at为域的长度。我没有添加到答案中,因为我想保持它简单和短小。 - user1079877

3
    public static string GetMaskedEmail(string emailAddress)
    {
        string _emailToMask = emailAddress;
        try
        {
            if (!string.IsNullOrEmpty(emailAddress))
            {
                var _splitEmail = emailAddress.Split(Char.Parse("@"));
                var _user = _splitEmail[0];
                var _domain = _splitEmail[1];

                if (_user.Length > 3)
                {
                    var _maskedUser = _user.Substring(0, 3) + new String(Char.Parse("*"), _user.Length - 3);
                    _emailToMask = _maskedUser + "@" + _domain;
                }
                else
                {
                    _emailToMask = new String(Char.Parse("*"), _user.Length) + "@" + _domain;
                }
            }
        }
        catch (Exception) { }
        return _emailToMask;
    }

0

Kotlin 扩展

/**
 * Format email id in the following format
 * (m••••••n@gmail.com)
 * only exception for 2 character username in that case it will be ••@gmail.com
 * @return formatted email
 */
fun String.maskEmailId(): String {
    return if (this.isNotNullOrEmpty() && this.indexOf('@') > 0) {
        val index = this.indexOf('@')
        val maskedUsername = if (index > 2) {
            "${this.substring(0, 1)}${"*".repeat(index-2)}${this.substring(index-1)}"
        } else {
            "*".repeat(index) + this.substring(index)
        }
        maskedUsername
    }  else ""
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接