这是代码的正则表达式。此正则表达式确定测试是否通过。
public static String markdownToHtml(String text) {
text = text.replaceAll("<([^a-zA-Z/])", "<$1");
// span - replaced < and > 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]));
}
我认为要通过我需要正确地转义双斜线。请问我该如何解决这个问题?我已经工作了好几天但它还没有工作
答案 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>
标记替换用下划线或星号包裹的任何内容。但是,要处理转义字符,他们需要进行负面的后观检查。要处理转义转义字符,它们还需要在执行此检查之前使用任何双转义符。第三个替换从测试中使用的特殊字符中删除转义字符。