Java 使用 \b 的正则表达式排序

Java Regex Ordering with \b

当 Java 正则表达式与字边界 \b 结合使用时,我遇到了一个奇怪的问题。 通读 Oracle - RegexBounds and RegularExpressions - 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 问题的 Whosebug 主题,但找不到相关主题。

引用 page 你 link 给:

There are three different positions that qualify as word boundaries:

  • Before the first character in the string, if the first character is a word character.
  • ...

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

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

这个修改后的正则表达式基于后视应该适合你:

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

RegEx Demo

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