【问题标题】:Replace emails in string in Java用Java替换字符串中的电子邮件
【发布时间】:2016-03-30 03:50:41
【问题描述】:

我需要保护文本中包含的电子邮件地址。理想情况下,找到一个可以更有效地执行此操作的正则表达式。

例子:

你好: 我的名字是 Alex,我的邮件是 alexmail@domain.com 但您可以回复 alexreply@other.domain.com

期望的输出:

你好: 我的名字是 Alex,我的邮件是 ale****@domain.com 但您可以回复 ale****@other.domain.com

逻辑是:保留前 3 个字符,其余的替换为 *,直到 @。

a@mail.com     => a****@mail.com
ab@mail.com    => ab****@mail.com
abc@mail.com   => abc****@mail.com
abcd@mail.com  => abc****@mail.com
abcde@mail.com => abc****@mail.com

现在,我用这种方式制作了一个保护邮件的功能,但是当它是包含多封电子邮件的文本时,我无法使用 replaceAll

public static String protectEmailAddress(String emailAddress) {
     String[] split = emailAddress.split("@");
     if (split[0].length() >= 3) {
         split[0] = split[0].substring(0, 3);  
     }
     emailAddress = StringUtils.join(split, "****@");

     return emailAddress;
}

所以基本上我需要的是一个很好的正则表达式。类似于this 的内容,但如果可能的话,包含邮件的另一部分。

谢谢...

【问题讨论】:

    标签: java regex email


    【解决方案1】:

    您可以使用(\\w{1,3})(\\w+)(@.*)

    String str = "alexreply@other.domain.com";
    str = str.replaceAll("(\\w{1,3})(\\w+)(@.*)", "$1****$3");
    System.out.println(str);
    

    输出

    ale****@other.domain.com
    

    解释:

    • (\\w{1,3}) :匹配 1 到 3 个单词字符
    • (\\w+) : 匹配一个或多个单词字符
    • (@.*) :匹配之后的任何内容(包括)@
    • $1 :表示第一组,即(\\w{1,3})
    • $3 :表示第三组,即(@.*)

    【讨论】:

    • 这项工作,但就像@arshajii 所说的那样,它很容易出现误报。但是,如果您确定字符串已经是一个电子邮件地址,则可以很好地替换它,但只能用于一个地址。
    • 我对正则表达式 \\w{1,3})(\\w+.*)(@.*) 做了一些小改动,以处理第一部分中带有点的较长地址。感谢这篇文章。
    【解决方案2】:

    你可能会使用类似的东西:

    text = text.replaceAll("\\S{1,4}@","****@");
    

    它应该将 1 到 4 个 ({1,4}) 非空白字符 (\\S) 后跟 @ 替换为 ****@

    所以它会以某种方式替换文本

    a@          -> ****@
    ab@         -> ****@
    abc@        -> ****@
    abcd@       -> ****@
    abcde@      -> a****@
    abcdef@     -> ab****@
    

    【讨论】:

    • 我的第一个方法是这个正则表达式,但需要显示前三个字符并将其余字符替换为 * 直到 @。所以我选择了函数。
    • 哦,所以逻辑是“保留 3 个字符并隐藏其余字符”而不是“隐藏最后 4 个字符”。将尝试更新它。
    • 这种方法的缺点是,如果我的文本中包含不属于电子邮件地址的@s,它很容易出现误报。首先使用正则表达式解析电子邮件地址通常不是一个好主意。
    • @arshajii 是的,解析电子邮件并不是一件容易的事,所以有很多陷阱会使我们的代码返回许多误报解决方案。最好的方法可能是使用可以找到所有电子邮件的库,然后手动更改它们(即使没有正则表达式的帮助)。
    • 你有什么图书馆吗?我经常使用 Apache Commons,但我没有发现任何东西......
    【解决方案3】:

    我建议以下方法:

    public static void main(String[] args) {
            String text = "Hi:"
                    + " "
                    + "My Name is Alex and my mail is alexmail@domain.com but you can reply to "
                    + "alexreply@other.domain.com."
                    + " a@mail.com"
                    + " abcd@mail.com";
    
            String emailPattern = "[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*"
                    + "      @[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})";
    
            emailPattern = "(?<emailHead>[_A-Za-z0-9-\\+]{1,3})+?(?<replacementEmailPart>[_A-Za-z0-9-\\+]*)*?(?<emailTail>@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})){1}";
    
            Pattern p = Pattern.compile(emailPattern);
    
            Matcher m = p.matcher(text);
    
            StringBuffer sb = new StringBuffer();
            while (m.find()) {
                String replStr = m.group("replacementEmailPart");
                if (replStr != null) {
                    replStr = replStr.replaceAll("[_A-Za-z0-9-\\+]", "*");
                } else {
                    replStr = "****";
                }
                m.appendReplacement(sb, m.group("emailHead")
                        + replStr
                        + m.group("emailTail"));
            }
            m.appendTail(sb);
            System.out.println(sb.toString());
        }
    

    【讨论】:

      【解决方案4】:

      这是检查字符串有效性的方法(是否为电子邮件)。 将您的文本拆分为单词,并使用此方法检查每个单词。如果是电子邮件,请用星号(*)替换它。

      public static boolean isValidEmail(String str) {
          String pattern = "^[\\w!#$%&’*+/=?`{|}~^-]+(?:\\.[\\w!#$%&’*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$";
          Pattern p = Pattern.compile(pattern);
          Matcher m = p.matcher(str);
          return m.matches();
      }
      

      【讨论】:

        【解决方案5】:

        正则表达式不是解决此问题的正确工具(请参阅:Using a regular expression to validate an email address)。另一种方法是按照以下方式做一些事情:

        1. 将您的信息拆分成文字(message.split("\\s+") 或类似的东西)。

        2. 对于每个单词,通过InternetAddress构造函数检查它是否是一个电子邮件地址:

          try {
              new InternetAddress(word, true);
              // valid e-mail address
          } catch (AddressException e) {
              // not an e-mail address
          }
          
        3. 如果单词是电子邮件地址,请使用您当前的功能“保护”它。

        4. 将所有单词重新组合成一封新邮件,其中电子邮件地址都受到保护。


        另一方面,如果你真的想使用正则表达式,那么……好吧……you asked for it

        【讨论】:

        • 我想我必须采用这个解决方案。我希望找到一个神奇的正则表达式来为我解决所有问题:D。但我担心使用这种方法的性能。
        猜你喜欢
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        • 2015-06-18
        • 2021-05-31
        • 2020-11-06
        • 1970-01-01
        • 2012-10-15
        • 2015-05-31
        相关资源
        最近更新 更多