如何使用\ Q \ E转义 - 使用DOTALL字面化unicode字符?

时间:2014-04-03 22:00:02

标签: java regex

我有以下代码,正则表达式是指定的输入,导致下面的输出结果如下。但是,unicode字符导致m.find()抛出异常。如果在文本中“Unicode”之前删除unicode char,一切正常。

所以,我尝试装饰我的正则表达式以使用\ Q \ E来逃避/计算任何unicode字符(不确定这是否是正确的方法或者我是否正确执行)。但是,它会阻止异常,但现在它与m.find()不匹配。

如何正确地转义此unicode(以及任何unicode char)?

        String text = "Hi\n\nyo keep this here\n\nUnicode b4 keep all from here\n\nyo\ncut me:\n\nThis should be deleted";
        Pattern PATTERN = Pattern.compile("^\\Q(.+?)\\nyo(?:(?!cut me:|\\nyo).)*cut me:\\E",
                Pattern.DOTALL);
        Matcher m = PATTERN.matcher(text);
        if (m.find()) {
            text = m.group(1);
            System.out.println(text);
        }

输出:

  

您好

     

哟保持这里

     

Unicode b4将所有内容保留在此处

2 个答案:

答案 0 :(得分:3)

使用\Q\E实际上会改变正则表达式的行为:正如您所写的那样,它将与该序列完全匹配:

(.+?)\\nyo(?:(?!cut me:|\\nyo).)*cut me:

也就是说,它通常会尝试找到parenthesis,然后是文字dot,后跟文字+,依此类推......


澄清一点:

final Pattern PATTERN = Pattern.compile("^\\Q(.+?)\\nyo(?:(?!cut me:|\\nyo).)*cut me:\\E", Pattern.DOTALL);
final Matcher m = PATTERN.matcher("(.+?)\\nyo(?:(?!cut me:|\\nyo).)*cut me:");
System.out.println(m.match());   // true

答案 1 :(得分:2)

正如另一个答案所说,\Q\E会导致正则表达式中的所有字符都被解释为与自己匹配的引用字符。

答案是升级到Java 8.该错误似乎已修复。

这是一个用全ASCII字符编写的程序,它复制了行为:

import java.util.regex.*;
class Test {
    public static void main(String[] args) {
        char[] special = Character.toChars(0x1F4F1);
        String text = "Hi\n\nyo keep this here\n\n" + new String(special) + "Unicode b4 keep all from here\n\nyo\ncut me:\n\nThis should be deleted";
        Pattern PATTERN = Pattern.compile("^(.+?)\\nyo(?:(?!cut me:|\\nyo).)*cut me:",
                Pattern.DOTALL);
        Matcher m = PATTERN.matcher(text);
        if (m.find()) {
            text = m.group(1);
            System.out.println(text);
        }
    }
}

使用Java 7编译并运行它会导致:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.charAt(String.java:695)
    at java.util.regex.Pattern$Slice.match(Pattern.java:3867)
    at java.util.regex.Pattern$GroupCurly.match0(Pattern.java:4360)
    at java.util.regex.Pattern$GroupCurly.match0(Pattern.java:4354)
    at java.util.regex.Pattern$GroupCurly.match(Pattern.java:4304)
    at java.util.regex.Pattern$Slice.match(Pattern.java:3870)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4615)
    at java.util.regex.Pattern$Curly.match1(Pattern.java:4185)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4134)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4556)
    at java.util.regex.Pattern$Begin.match(Pattern.java:3472)
    at java.util.regex.Matcher.search(Matcher.java:1199)
    at java.util.regex.Matcher.find(Matcher.java:592)
    at Test.main(Test.java:9)

使用Java 8:

Hi

yo keep this here

?Unicode b4 keep all from here

(我的系统无法正确输出特殊字符。)