【发布时间】:2009-06-10 14:14:17
【问题描述】:
当谈到正则表达式时,我是一个相对新手,但我开始掌握它的窍门。我开始在 java 中编写一个方法来“链接”一个字符串 - 也就是说,扫描它以查找任何 url 引用(即“http://...”)或 看起来 像 web 的字符串地址(“www.example.com...”)
例如,如果我有一个如下所示的字符串:
My favorite site is http://www.example.com. What is yours?
通过方法运行它后,你会得到一个字符串,上面写着:
My favorite site is <a href="http://www.example.com">http://www.example.com</a>. What is yours?
在网上搜索了一段时间后,我终于能够拼凑出不同的表达方式,帮助我做我正在寻找的事情(一些例子包括实际 url 中 url 末尾的尾随句点,一些编码网址已经在锚标签等)
这是我目前所拥有的:
public static String toLinkifiedString(String s, IAnchorBuilder anchorBuilder)
{
if (IsNullOrEmpty(s))
{
return Empty;
}
String r = "(?<![=\"\"\\/>])(www\\.|(http|https|ftp|news|file)(s)?://)([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?([^.|'|# |!])";
Pattern pattern = Pattern.compile(r, Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(s);
if (anchorBuilder != null)
{
return matcher.replaceAll(anchorBuilder.createAnchorFromUrl("$0"));
}
return matcher.replaceAll("<a href=\"$0\">$0</a>"); // group 0 is the whole expression
}
public interface IAnchorBuilder
{
public String createAnchorFromUrl(String url);
}
还有一个简单的 toLinkifiedString 版本,它只接受字符串 s - 它只是调用 toLinkifiedString(s, null)
就像我说的那样,这种模式可以捕获我需要捕获的所有内容,并且 replaceAll 对每种情况都非常有效,除非链接以 www 开头。如果匹配以“www”而不是协议开头,如“http”或“ftp”,我想有条件地在结果链接前添加“http://”。那就是:
MyClass.toLinkifiedString("go to www.example.org")
应该返回
go to <a href="http://www.example.com">www.example.org</a>
匹配组如下:
- $0 - 找到的实际网址:http://www.example.org 或 www.example.net
- $1 - 协议匹配(“http://”或“www”表示无协议的链接)
我想我想做的事,在伪代码中是这样的:
matcher.replaceAll("<a href="(if protocol = "www", insert "http://" + url - otherwise, insert url">url</a>"
这可能吗?或者我是否应该对只能从以“http://...”开头的链接创建锚点感到满意 :)
感谢任何人提供的任何帮助
【问题讨论】:
-
你不需要使用相当这么多的反斜杠。 :D
-
@mjd79:你的正则表达式很乱。即使您开始掌握它的窍门,您也不应该在没有完全理解它们的含义之前从 Internet 上复制示例。我可以在其中看到许多错误的假设(关于正确的字符转义和字符类的机制)。如何在文本中查找 URL 的问题已经多次出现,我建议您通过 Google 的方式查看 SO。至少这里的正则表达式通常带有经过验证的解释。 :)