正则表达式匹配双反斜杠

时间:2018-03-31 13:16:24

标签: java regex

这是代码的正则表达式。此正则表达式确定测试是否通过。

    public static String markdownToHtml(String text) {
    text = text.replaceAll("<([^a-zA-Z/])", "&lt;$1");

    // span - replaced &lt; and &gt; with <>
    text = ReplaceCallback.replace("(?s)<\\s?span([^\\/\n]*)>((?:(?!<\\/).)+) 
    <\\/\\s?span\\s?>",
            text, createSpan);
 // strong
    text = text.replaceAll("(?s)__(.*?)__", "<strong>$1</strong>");
    text = text.replaceAll("(?s)\\*\\*(.*?)\\*\\*", "<strong>$1</strong>");
    // emphasis
    text = text.replaceAll("(?s)_([^\\s][^_\n]*)_", "<em>$1</em>");
    text = text.replaceAll("(?s)\\*([^\\s][^\\*\n]*)\\*", "<em>$1</em>");
    // links
    text = text.replaceAll("(?s)\\[([^\\]]*)\\]\\(([^\\)]+)\\)",
            "<a href=\"$2\" target=\"_blank\">$1</a>");
    // headers - requires ^ or breaks <font color="#f58a1f">color</font>
    text = ReplaceCallback.replace("(?s)^(#+)([^\n]*)$", text, createHeader);
    // paragraphs
    text = ReplaceCallback.replace("(?s)([^\n]+)\n", text, createParagraph);

      //create intermittent replacements keys for special characters
        text = text.replaceAll("(?s)\\\\#", "==");
        text = text.replaceAll("(?s)\\\\\\*", "@@");
        text = text.replaceAll("(?s)\\\\_", "&&");
       // replace intermittent keys
        text = text.replaceAll("(?s)==", "#");
        text = text.replaceAll("(?s)@@", "*");
        text = text.replaceAll("(?s)&&", "_");
        return text;
        }

这些都是需要满足的测试。包含四个反斜杠的测试无法正常工作

 @Test
public void markDownToHtmlEscapesBackslash() {
    String[][] twoDTestCase =  {{"A\\_B\\_C", "A_B_C"},
            {"_A\\_B\\_C_", "<em>A_B_C</em>"},
            {"A_B\\_C", "A_B_C" },
            {"A\\_B_C", "A_B_C"},
            {"A_B_C", "A<em>B</em>C"},
            {"\\__AB\\__", "_<em>AB_</em>"},
            {"\\\\_AB\\_\\\\_", "\\<em>AB_\\</em>"},
            {"A\\*B\\*C", "A*B*C"},
            {"*A\\*B\\*C*", "<em>A*B*C</em>"},
            {"A*B\\*C", "A*B*C"},
            {"A*B*C", "A<em>B</em>C"},
            {"\\**AB\\**", "*<em>AB*</em>"},
            {"\\\\*AB\\*\\\\*", "\\<em>AB*\\</em>"},
            {"\\a\\ b\\*c\\d\\_e", "\\a\\ b*c\\d_e"},
            {"\\#1", "#1"},
            {"\\#\\# 2", "## 2"},
            {"works \\#when not required too", "works #when not required too"},
            {"\\", "\\"},
            {"\\\\", "\\"},
            {"\\\\\\", "\\\\"}
             };

    for (String[] testCase: twoDTestCase) {
        Assert.assertEquals(testCase[1], TextUtils.markdownToHtml(testCase[0]));
    }

我认为要通过我需要正确地转义双斜线。请问我该如何解决这个问题?我已经工作了好几天但它还没有工作

1 个答案:

答案 0 :(得分:1)

这是因为反斜杠在Java中用作转义字符,它实际上比你想象的更糟糕!

在Java字符串中,单个反斜杠用于转义特殊字符 - &#34; \ n&#34;是换行符,&#34; \ t&#34;是一个标签&#34;等等&#34; \&#34;本身会给编译器错误。所以&#34; \&#34; isn&#39; ta双反斜杠文字 - 第一个反斜杠转义第二个,所以java知道第二个反斜杠不应该逃避它后面的引号 - 它是一个单字反斜杠作为文字字符串。 / p>

当你来做正则表达时,这会变得更糟,因为你正在发现!反斜杠是java正则表达式中的也是转义字符。这意味着当你想使用正则表达式匹配文字反斜杠时,你需要一个文字双反斜杠。但要在java中获得双重反斜杠,您需要四倍反斜杠。

所以,如果你在Java中看到像"(?s)\\\\#"这样的正则表达式,它正在寻找匹配\#,但要在java中输入它,你需要"\\#"

您可以在this answer中了解详情。

编辑 - 我对如何解决这个问题感兴趣,所以这就是我想出来的 - 它似乎通过了你所有的测试用例:

    text = text.replaceAll("(?<!\\\\)((\\\\\\\\)*)_(.*)(?<!\\\\)((\\\\\\\\)*)_", "$2<em>$3$4</em>");
    text = text.replaceAll("(?<!\\\\)((\\\\\\\\)*)\\*(.*)(?<!\\\\)((\\\\\\\\)*)\\*", "$2<em>$3$4</em>");
    text = text.replaceAll("\\\\([*_#\\\\])", "$1");

前两个规则用<em>标记替换用下划线或星号包裹的任何内容。但是,要处理转义字符,他们需要进行负面的后观检查。要处理转义转义字符,它们还需要在执行此检查之前使用任何双转义符。第三个替换从测试中使用的特殊字符中删除转义字符。