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

PNS*_*PNS 23 java regex escaping

在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");
}
Run Code Online (Sandbox Code Playgroud)

毫不奇怪,上面代码产生的输出是:

Regex 1: \d+\.\d+
    Match
Regex 2: \Qd+.d+\E
    No match
Run Code Online (Sandbox Code Playgroud)

也就是说,regex1匹配1.2regex2("动态"构建)不匹配(相反,它匹配文字字符串d+.d+).

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

如果有的话,那就是静态escape()方法java.util.regex.Pattern,输出

Pattern.escape('.')
Run Code Online (Sandbox Code Playgroud)

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

Pattern.escape(',')
Run Code Online (Sandbox Code Playgroud)

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

Pattern.escape('d')
Run Code Online (Sandbox Code Playgroud)

可以产生"\d",因为'd'用于表示数字(虽然在这种情况下逃避可能没有意义,因为'd'可能意味着文字'd',这不会被正则表达式的插入者误解为其他东西,就像这样'.').

Fer*_*nch 27

我写了这个模式:

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

并在此方法中使用它:

String escapeSpecialRegexChars(String str) {

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
}
Run Code Online (Sandbox Code Playgroud)

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

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*");
}
Run Code Online (Sandbox Code Playgroud)

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

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
Run Code Online (Sandbox Code Playgroud)

  • 这个对我不起作用(至少在Scala中),但是这个做了:"[\\ {\\} \\(\\)\\ [\\] \\.\\ + \\*\\ ^ \\ $ \\\\\\ |?]"` (3认同)

Gra*_*ray 25

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

我不是100%肯定这就是你在这里问的问题.如果您正在寻找一种方法来创建可以在正则表达式模式中使用的常量,那么只需将它们预先设置就"\\"可以工作但是没有很好的Pattern.escape('.')功能来帮助解决这个问题.

所以如果你想匹配"\\d"(字符串\d而不是小数字符)那么你会这样做:

// this will match on \d as opposed to a decimal character
String matchBackslashD = "\\\\d";
// as opposed to
String matchDecimalDigit = "\\d";
Run Code Online (Sandbox Code Playgroud)

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

matchPeriod = "\\.";
matchPlus = "\\+";
matchParens = "\\(\\)";
... 
Run Code Online (Sandbox Code Playgroud)

在您的帖子中,您使用该Pattern.quote(string)方法.你可能知道这个包间你的模式"\\Q""\\E"因此即使它恰好有它特殊的正则表达式字符(可以匹配字符串+,.,\\d,等)


Att*_*ila 7

正则表达式匹配器知道你正在寻找数字而不是字母的唯一方法d是逃避字母(\d).要在java中键入正则表达式转义字符,您需要转义它(所以\变为\\).因此,没有办法为特殊的正则表达式字符键入双反斜杠.

  • 为了清楚术语,向非特殊字符添加反斜杠不称为转义。写 `\d` 无论如何都不会“逃避字母”`d`。相反,它创建了一个完全不同的概念,一个代表数字的字符类。转义的一个例子是你的第二种情况,用 `\\` 来表示斜杠字符。 (2认同)

whe*_*ler 5

Pattern.quote(String s)那种你想要做什么。然而,它还有一点不足之处;它实际上并没有转义单个字符,只是用\Q...\E.

没有一种方法可以完全满足您的要求,但好消息是转义 Java 正则表达式中的所有特殊字符实际上相当简单:

regex.replaceAll("[\\W]", "\\\\$0")
Run Code Online (Sandbox Code Playgroud)

为什么这样做?好吧,文档Pattern特别指出,可以转义不一定要转义的非字母字符:

在任何不表示转义结构的字母字符之前使用反斜杠是错误的;这些是为正则表达式语言的未来扩展保留的。可以在非字母字符之前使用反斜杠,而不管该字符是否是未转义结构的一部分。

例如,;不是正则表达式中的特殊字符。但是,如果你逃避它,Pattern仍然会解释\;;. 以下是更多示例:

  • >变成\>等价于>
  • [变成了\[它的转义形式[
  • 8还在8
  • \)成为和\\\)的转义形式。\(

注意:关键是“非字母”的定义,在文档中真正的意思是“非单词”字符,或者字符集之外的字符[a-zA-Z_0-9]