簡體   English   中英

未轉義的Java在正則表達式matcher.find()中不匹配

[英]Unescaped java not matching in regex matcher.find()

我有以下基本上與“匹配此:”匹配的代碼,並保留第一句話。 但是,有時會有Unicode字符傳遞到文本中,從而導致在其他更復雜的正則表達式上回溯。 轉義似乎減輕了超出范圍例外的回溯索引。 但是,現在正則表達式不匹配。

我想知道的是,為什么此正則表達式在轉義時不匹配? 如果您注釋掉了轉義/ 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);

我想知道的是,為什么此正則表達式在轉義時不匹配?

當您轉義類似於"foo\\nbar"字符串時,其輸出類似於

foo
bar

你會得到"foo\\\\nbar" ,它看起來像

foo\nbar

發生這種情況是因為StringEscapeUtils.escapeJava也轉義了\\n並將其替換為\\\\n ,所以它不再是行分隔符而是簡單的文字,因此無法與^$匹配。

可能的解決方案是在StringEscapeUtils.escapeJava之后用"\\n"代替"\\\\n" 您將需要在這里小心,不要“ unscapee”真實的"\\\\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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM