首页 文章

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

提问于
浏览
19

在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.2regex2 ( Build "dynamically")不匹配(相反,它匹配文字字符串 d+.d+ ) .

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

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

Pattern.escape('.')

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

Pattern.escape(',')

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

Pattern.escape('d')

可以产生 "\d" ,因为 'd' 用于表示数字(虽然在这种情况下转义可能没有意义,因为 'd' 可能意味着字面意思 'd' ,这不会被正则表达式的互操作者误解为其他东西,如同情况一样 '.' ) .

6 回答

  • 24

    在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";
    

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

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

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

  • 1

    我写了这个模式:

    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.*")
    }
    
  • 23

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

  • 6

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

  • 0

    使用

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

    将按原样 yourcontent 给出结果

  • 0

    使用此实用程序函数 escapeQuotes() 以便在RegualrExpressionGroupsSets 之间转义字符串 .

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

    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\\)" .

    Example :要匹配的字符串 (hello) 和带有组的正则表达式是 (\(hello\)) . 从这里形成你只需要转义匹配的字符串,如下所示 . 在线测试Regex

    public static void main(String[] args) {
        String matched = "(hello)", regexExpGrup = "(" + escapeQuotes(matched) + ")";
        System.out.println("Regex : "+ regexExpGrup); // (\(hello\))
    }
    

相关问题