我有以下代码基本匹配“匹配这个:”并保留第一句话。但是,有时会将unicode字符传递到文本中,导致其他更复杂的正则表达式的回溯。转义似乎可以减少回溯指数超出范围异常。但是,现在正则表达式不匹配。
我想知道的是为什么这个正则表达式在转义时不匹配?如果你注释掉escape / unescape java就行了。
String text = "Keep this\n\n"
+ "Match this:\n\nDelete 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);
答案 0 :(得分:3)
我想知道的是为什么这个正则表达式在转义时不匹配?
当你像"foo\nbar"
这样的字符串被转义时,其打印类似于
foo
bar
你得到"foo\\nbar"
的印刷品看起来像
foo\nbar
之所以发生这种情况,是因为StringEscapeUtils.escapeJava
也会\n
转义并将其替换为\\n
,因此它不再是行分隔符而是简单的文字,因此无法与之匹配^
或$
。
可能的解决方案可能是在"\\n"
之后用"\n"
替换StringEscapeUtils.escapeJava
。你需要在这里小心,而不是" unescapee"替换后的真实"\\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);
}
此方法可防止转义\r
和\n
。