38

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

也就是说,regex1匹配1.2but regex2(它是“动态”构建的)不匹配(相反,它匹配文字 string d+.d+)。

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

如果有,比方说,一个静态escape()方法java.util.regex.Pattern,输出

Pattern.escape('.')

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

Pattern.escape(',')

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

Pattern.escape('d')

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

4

7 回答 7

36

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等)

于 2012-05-19T12:11:11.960 回答
32

我写了这个模式:

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) + ".*");
}

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

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
于 2014-09-15T17:25:34.037 回答
8

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

于 2012-05-19T10:47:20.740 回答
5

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

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

regex.replaceAll("[\\W]", "\\\\$0")

为什么这行得通?好吧,文档Pattern专门说它允许转义不一定必须转义的非字母字符:

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

例如,;不是正则表达式中的特殊字符。但是,如果你逃避它,Pattern仍然会解释\;;. 这里还有几个例子:

  • >变成\>相当于>
  • [成为\[的转义形式[
  • 8还在8
  • \)成为\\\)它是转义形式\(连接。

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

于 2019-05-24T21:39:03.170 回答
3

使用此实用程序函数可以escapeQuotes()转义.RegualrExpression

要转义的正则表达式文字列表<([{\^-=$!|]})?*+.>

public class RegexUtils {
    static String escapeChars = "\\.?![]{}()<>*+-=^$|";
    public static String escapeQuotes(String str) {
        if(str != null && str.length() > 0) {
            return str.replaceAll("[\\W]", "\\\\$0"); // \W designates non-word characters
        }
        return "";
    }
}

Pattern类中,反斜杠字符('\')用于引入转义结构。字符串文字"\(hello\)"是非法的,会导致编译时错误;为了匹配字符串 (hello),"\\(hello\\)"必须使用字符串文字。

示例:要匹配的字符串(hello)和带有组的正则表达式是(\(hello\)). 在此处形成您只需要转义匹配的字符串,如下所示。Test Regex online

public static void main(String[] args) {
    String matched = "(hello)", regexExpGrup = "(" + escapeQuotes(matched) + ")";
    System.out.println("Regex : "+ regexExpGrup); // (\(hello\))
}
于 2019-01-08T08:00:27.100 回答
2

同意 Gray,因为您可能需要您的模式同时具有文字(\[,\])和元字符([,])。所以使用一些实用程序,您应该能够首先转义所有字符,然后您可以添加要添加到相同模式的元字符。

于 2013-10-09T01:49:04.267 回答
1

利用

pattern.compile("\"");
String s= p.toString()+"yourcontent"+p.toString();

将按原样给出yourcontent结果

于 2017-04-28T09:57:33.520 回答