【问题标题】:Negating a Regular Expression for string replacement否定正则表达式以进行字符串替换
【发布时间】:2011-12-14 04:21:26
【问题描述】:

我有以下代码可以用 Java 替换字符串中的电子邮件地址:

addressStr.replaceFirst("([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})", "")

因此,带有John Smith <john@smith.com> 的字符串将变为John Smith <>。我该如何否定它,以便它将替换所有与电子邮件地址不匹配的内容,并将最终结果设为 john@smith.com

我尝试将^?<= 放在前面但不起作用。

【问题讨论】:

    标签: java regex regex-negation


    【解决方案1】:

    嗯,您需要更改的不是正则表达式,而是调用代码。您的正则表达式匹配电子邮件地址(以一种奇怪的方式),replace() 将其从字符串中删除。

    所以就用

    Pattern regex = Pattern.compile("([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})");
    Matcher regexMatcher = regex.matcher(addressStr);
    if (regexMatcher.find()) {
        address = regexMatcher.group();
    }
    

    【讨论】:

    • 我试过这个,但它给我一个Exception in thread "main" java.lang.IllegalStateException: No match found。当我打印regexMatcher.matches() 时,它返回false,但regexMatcher.find() 返回true。这很奇怪。它们有什么区别,为什么regexMatcher.group(); 会抛出这个异常?
    • 呃,对不起,你需要先做一个find()。会编辑。 matcher() 不起作用,因为它需要匹配整个字符串。
    • 我认为您在上面的评论中指的是matches(),而不是matcher(),Tim。
    【解决方案2】:

    用于捕获电子邮件的完整 Java 正则表达式如下:

    "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
    

    查看https://www.rfc-editor.org/rfc/rfc2822#section-3.4.1 了解更多信息。

    有点复杂,但它适用于所有已知和有效的电子邮件格式(你的不允许像 bob+bib@gmail.com 这样有效的邮件)。

    对于您的问题,如多次所述,只需找到(窃取 Tim Pietzcker 的一段代码):

    Pattern regex = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])");
    Matcher regexMatcher = regex.matcher(addressStr);
    foundMatch = regexMatcher.find();
    

    【讨论】:

    • 至少有一个人在开始处理小细节之前指出了明显的缺陷。我已经看到太多网站的验证器完全损坏了,这已经不再有趣了:/如果可以的话,我很乐意给 +2..
    • 感谢您的建议!但是 regexMatcher.find();和 regexMatcher.matches();返回布尔值而不是字符串。我怎样才能从源字符串中获取电子邮件地址的字符串?
    【解决方案3】:

    你可以试试:

    String mailId = Pattern.compile(regexp, Pattern.LITERAL).matcher(addressStr).group();
    

    这里的想法是获取匹配的字符串,而不是尝试用空白替换其他所有内容。如果此操作重复,您可以将模式提取到字段中。

    【讨论】:

    • Pattern.LITERAL 导致模式字符串被视为文字字符串,但这个问题显然需要将其视为正则表达式。此外,matcher(String) 仅创建一个Matcher 对象,它不会尝试应用正则表达式——正如其他人所说,您需要通过调用(在这种情况下)find() 来跟进。事实上,你的代码总是会抛出一个IllegalStateException
    【解决方案4】:

    只是不要替换....改用匹配项。

    【讨论】:

      猜你喜欢
      • 2018-07-13
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多