【问题标题】:Java Regex Ordering with \b使用 \b 进行 Java 正则表达式排序
【发布时间】:2015-01-05 22:13:59
【问题描述】:

当与单词边界\b 结合使用时,我遇到了 Java 正则表达式的一个奇怪问题。 通读Oracle - RegexBoundsRegularExpressions - WordBoundaries

下面是我的正则表达式(Java 字符串)(用于电子邮件地址)

"\\b[A-Z0-9._!#$%&'*+-/=?^`{}|~]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$"

此正则表达式匹配电子邮件test$@example.com,但不匹配$test@example.com

但是,当我删除 \b(Java 字符串 \\b)时,它会匹配这两个电子邮件。正则表达式中的所有特殊字符都是这种情况。

\b 在正则表达式的排序中发生了什么?我认为[A-Z0-9._!#$%&'*+-/=?^`{}|~]+ 应该以任何顺序匹配文本,而不管\b

代码片段:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidationUtil {

    private static final String EMAIL_ADDRESS_REGEX = "\\b[A-Z0-9._!#$%&'*+-/=?^`{}|~]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$";
    private static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile(EMAIL_ADDRESS_REGEX, Pattern.CASE_INSENSITIVE);

    public static boolean isValidEmail(String email) {
        if (email == null) {
            return false;
        }
        Matcher matcher = EMAIL_ADDRESS_PATTERN.matcher(email);
        return matcher.matches();
    }
}

在这个问题之后,我将正则表达式验证移至apache-commons EmailValidator。但仍然很好奇为什么会出现这种奇怪的行为。

我浏览了许多关于 \b 问题的 stackoverflow 主题,但找不到相关主题。

【问题讨论】:

    标签: java regex word-boundary


    【解决方案1】:

    引用您链接到的page

    有资格作为单词边界的三个不同位置:

    • 在字符串的第一个字符之前,如果第一个字符是单词字符。
    • ...

    第一个字符 $ 不是单词字符,因此 \b 在字符串的开头不匹配,因此整个正则表达式不匹配。

    【讨论】:

    • 上面还写着Between two characters in the string, where one is a word character and the other is not a word character. 所以你的观点和这一点意味着第一个字符应该总是一个单词字符?
    • @Baskar:有 3 个不同(类型)的位置,您引用的是边界的另一个可能位置。
    • @Baskar:当您匹配以\b 开头的正则表达式时,另一点不适用。只有第一点可以(这就是我只引用第一点的原因)。
    【解决方案2】:

    首先,您需要将未转义的连字符放在字符类中的第一个或最后一个位置。第二个您不能在$ 之前使用字边界,因为$ 不被视为字字符。

    这个修改后的正则表达式lookbehind based应该适合你:

    (?<!\w)[\w.!#$%&'*+/=?^`{}|~-]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$
    

    RegEx Demo

    这里(?&lt;!\w) 表示如果前面没有单词字符则匹配。

    【讨论】:

    • (?&lt;!\w) 仍然不能替代 \b 因为这假定在“单词”的开头之前有一个字符。如果它位于字符串的开头,它将不起作用。我想你可以尝试预先设置一个假字符。
    • 我不确定它是否可以替代\b,但它匹配test$@example.com$test@example.com。谢谢。但是,我不是在寻找 \b 的替代品,而是有兴趣了解更多关于 \b 的信息。
    • @JosephK.Strauss: (?&lt;!\w) 不假设前面有一个字符 - 当前面没有字符时,\w 不能匹配并且断言简单地返回 true 和继续看续集。
    • @anubhava: [^\B] 在 Java 正则表达式 IIRC 中没有任何意义。
    • 对不起,我应该在评论之前检查一下,我猜这是 PCRE 特定的。
    猜你喜欢
    • 2023-04-09
    • 2017-09-20
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多