转义 Java 正则表达式中的特殊字符

2022-09-01 03:32:36

Java或任何开源库中是否有任何方法可以转义(不引用)特殊字符(元字符),以便将其用作正则表达式?

这在动态构建正则表达式时非常方便,而无需手动转义每个单独的字符。

例如,考虑一个简单的正则表达式,如 将数字与小数点(如 )以及以下代码匹配:\d+\.\d+1.2

String digit = "d";
String point = ".";
String regex1 = "\\d+\\.\\d+";
String regex2 = Pattern.quote(digit + "+" + point + digit + "+");

Pattern numbers1 = Pattern.compile(regex1);
Pattern numbers2 = Pattern.compile(regex2);

System.out.println("Regex 1: " + regex1);

if (numbers1.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

System.out.println("Regex 2: " + regex2);

if (numbers2.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

毫不奇怪,上述代码生成的输出是:

Regex 1: \d+\.\d+
    Match
Regex 2: \Qd+.d+\E
    No match

也就是说,匹配但(“动态”构建的)不匹配(相反,它与文本字符串匹配)。regex11.2regex2d+.d+

那么,有没有一种方法可以自动转义每个正则表达式元字符?

假设有一个静态方法,则escape()java.util.regex.Pattern

Pattern.escape('.')

将是字符串,但是"\."

Pattern.escape(',')

应该只产生,因为它不是元字符。同样地","

Pattern.escape('d')

可以产生,因为用于表示数字(尽管在这种情况下转义可能没有意义,因为可能意味着字面上的意思,这不会被正则表达式interpeter误解为其他东西,就像这种情况一样)。"\d"'d''d''d''.'


答案 1

Java或任何开源库中是否有任何方法可以转义(不引用)特殊字符(元字符),以便将其用作正则表达式?

如果您正在寻找一种创建可以在正则表达式模式中使用的常量的方法,那么只需在它们前面加上应该就可以了,但是没有很好的函数可以帮助解决这个问题。"\\"Pattern.escape('.')

因此,如果您尝试匹配(字符串而不是十进制字符),那么您将执行以下操作:"\\d"\d

// this will match on \d as opposed to a decimal character
String matchBackslashD = "\\\\d";
// as opposed to
String matchDecimalDigit = "\\d";

Java 字符串中的 4 个斜杠在正则表达式模式中变为 2 个斜杠。正则表达式模式中的 2 个反斜杠与反斜杠本身匹配。在任何特殊字符前面加上反斜杠会将其转换为普通字符,而不是特殊字符。

matchPeriod = "\\.";
matchPlus = "\\+";
matchParens = "\\(\\)";
... 

在你的帖子中,你使用Pattern.quote(string)方法。此方法将你的模式包装在 和 之间,因此即使字符串中恰好具有特殊的正则表达式字符(、、、等),您也可以匹配该字符串。"\\Q""\\E"+.\\d


答案 2

我写了这个模式:

Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");

并在此方法中使用它:

String escapeSpecialRegexChars(String str) {

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
}

然后你可以像这样使用它,例如:

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*");
}

我们需要这样做,因为在转义之后,我们添加了一些正则表达式。如果没有,您可以简单地使用和:\Q\E

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}