未转义的 java 在正则表达式 matcher.find() 中不匹配



我有以下代码,基本上匹配"匹配这个:"并保留第一句话。 但是,有时会将 unicode 字符传递到文本中,从而导致其他更复杂的正则表达式的回溯。转义似乎可以缓解回溯指数超出范围的异常。 但是,现在正则表达式不匹配。

我想知道的是为什么这个正则表达式在转义时不匹配? 如果你注释掉 escape/unescape java 会排列所有内容。

    String text = "Keep thisnn"
            + "Match this:nnDelete 📱 this";
    text = org.apache.commons.lang.StringEscapeUtils.escapeJava(text);
    Pattern PATTERN = Pattern.compile("^Match this:$",
            Pattern.MULTILINE);
    Matcher m = PATTERN.matcher(text);
    if (m.find()) {
        text = text.substring(0, m.start()).replaceAll("[\n]+$", "");
    }
    text = org.apache.commons.lang.StringEscapeUtils.unescapeJava(text);
    System.out.println(text);

我想知道的是为什么这个正则表达式在转义时不匹配?

当您转义字符串时,打印的字符串类似于 "foonbar"

foo
bar

你得到"foo\nbar"打印看起来像

foonbar

发生这种情况是因为StringEscapeUtils.escapeJava转义也n并用\n替换它,所以它不再是行分隔符,而是简单的文字,所以它不能与^$匹配。

可能的解决方案可能是在StringEscapeUtils.escapeJava后用"n"替换回"\n"。您在这里需要小心,不要"逃脱"真正的"\n"更换后会给您带来"\\n"打印看起来像\n.所以也许使用

text = org.apache.commons.lang3.StringEscapeUtils.escapeJava(text);
text = text.replaceAll("(?<!\\)\\n", "n");// escape `n` 
                                               // if it is not preceded with ``
//do your job
//and now you can unescape your text (n will stay n)
text = org.apache.commons.lang3.StringEscapeUtils.unescapeJava(text);

另一种选择可能是创建自己的实现,类似于 StringEscapeUtils.escapeJava .如果你看一下这个方法体,你会看到

return ESCAPE_JAVA.translate(input);

ESCAPE_JAVA在哪里

CharSequenceTranslator ESCAPE_JAVA = 
  new LookupTranslator(
    new String[][] { 
      {""", "\""},
      {"\", "\\"},
  }).with(
    new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE())
  ).with(
    UnicodeEscaper.outsideOf(32, 0x7f) 
);

EntityArrays.JAVA_CTRL_CHARS_ESCAPE() 返回克隆

String[][] JAVA_CTRL_CHARS_ESCAPE = {
    {"b", "\b"},
    {"n", "\n"},
    {"t", "\t"},
    {"f", "\f"},
    {"r", "\r"}
};

数组。因此,如果您在此处提供自己的表,该表将明确告知n应该保持原样(因此应该将其替换为自身n),您的代码将忽略它。

所以这就是你自己的实现的样子

private static CharSequenceTranslator translatorIgnoringLineSeparators = 
    new LookupTranslator(
        new String[][] { 
                { """, "\"" }, 
                { "\", "\\" }, 
        }).with(
                new LookupTranslator(new String[][] {
                        { "b", "\b" },
                        { "n", "n"  },//this will handle `n` and will not change it
                        { "r", "r"  },//this will handle `r` and will not change it
                        { "t", "\t" }, 
                        { "f", "\f" },
        })).with(UnicodeEscaper.outsideOf(32, 0x7f));
public static String myJavaEscaper(CharSequence input) {
    return translatorIgnoringLineSeparators.translate(input);
}

此方法将防止转义rn

最新更新