我在Java webapp中有一个所见即所得的文本区域。用户可以输入文本并对其进行样式设置或粘贴一些已经HTML格式的文本。
我要做的是 linkify 文本。这意味着,将文本中的所有可能的URL转换为它们的“工作对应物”,即添加< a href =“...”> ...< / A>
当我所拥有的只是纯文本时,此解决方案可以:
String r = "http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
Pattern pattern = Pattern.compile(r, Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(comment);
comment = matcher.replaceAll("<a href=\"$0\">$0</a>"); // group 0 is the whole expression
但问题是当有一些已经格式化的文本时,即它已经具有&lt; a href =“...”&gt; ...&lt; / A&GT;标签
因此,只要找到两个HTML标记(&lt; a&gt;)之间的文本,我就会找到模式不匹配的方法。我已经读过这可以通过lookahead或lookbehind来实现,但我仍然无法使其发挥作用。我确信我做错了因为正则表达式仍然匹配。是的,我一直在玩/调试组,将$ 0改为$ 1等。
有什么想法吗?
答案 0 :(得分:9)
你很亲密。您可以像这样使用“负面观察”:
(?<!href=")http:// etc
所有以href开头的结果都将被忽略。
答案 1 :(得分:1)
如果你想使用正则表达式,(虽然我认为首先解析为XML / HTML更加健壮)我认为前瞻或后瞻是有道理的。第一次尝试可能是在正则表达式的末尾添加它:
(?!</a>)
含义:如果之后关闭了标签,则不匹配。 (当然,这可以永远调整。)但这并不好用,因为给出了字符串
<a href="...">http://example.com/</a>
这个正则表达式将尝试匹配“http://example.com/”,由于前瞻(我们希望)失败,然后回溯贪婪的限定符最后匹配“{ {3}}“相反,它没有跟在它之后。
您可以在+,*和?上使用http://example.com解决后一个问题。运营商 - 只需坚持一个+。这可以防止他们进行反向跟踪。出于性能原因,这可能也不错。
这对我有用(注意三个额外的+):
String r = "http(s)?://([\\w+?\\.\\w+])++([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*+)?+(?!</a>)";
答案 2 :(得分:1)
如果你真的想用正则表达式来做,那么:
String r = "(?<![=\"\\/>])http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
e.g。检查网址是否跟随=“或/&gt;
答案 3 :(得分:0)
也许html解析更适合你(例如htmlparser)。然后你可以拥有html节点,只有文本中的“linkify”链接,而不是属性。
答案 4 :(得分:0)
如果你必须自己动手,至少要看一下Markdown开源实现中使用的算法/模式,例如MarkdownJ。