当谈到正则表达式时,我是一个相对新手,但我开始掌握它。我开始在java中编写一个方法来“链接”一个字符串 - 也就是说,扫描它以获取任何url引用(即“http:// ...”)或看起来像的字符串。地址(“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?
在网上搜索了一段时间后,我终于能够将不同表达式的部分拼凑在一起,帮助我做我正在寻找的事情(一些例子包括在实际网址的网址末尾的尾随句点,一些编码已经在锚标签中的网址等。)
这是我到目前为止所做的:
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 - 它只调用了LinksifiedString(s,null)
就像我说的那样,这种模式正在捕捉我需要捕获的所有内容,而且除了链接以www开头的情况外,replaceAll对每种情况都很有效。如果匹配以“www”开头而不是像“http”或“ftp”这样的协议,我想在结果链接前有条件地添加“http://”。那就是:
MyClass.toLinkifiedString("go to www.example.org")
应该返回
go to <a href="http://www.example.com">www.example.org</a>
匹配组如下:
我想我想做的事情,在伪代码中是这样的:
matcher.replaceAll("<a href="(if protocol = "www", insert "http://" + url - otherwise, insert url">url</a>"
这可能吗?或者我应该只对能够从以“http:// ...”开头的链接创建锚点感到高兴:)
感谢任何人提供的任何帮助
答案 0 :(得分:10)
对于你的具体问题,肯定会采用Tomalak所说的回调函数。
对于所有那些斜线的问题,以及各种其他奇怪的事情......
以下是您当前的Java正则表达式跨行分割:
(?<![=\"\"\\/>])
(www\\.|(http|https|ftp|news|file)(s)?://)
([\\w+?\\.\\w+])+
([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?
([^.|'|# |!])
与非Java正则表达式相同(没有Java字符串转义):
(?<![=""\/>])
(www\.|(http|https|ftp|news|file)(s)?://)
([\w+?\.\w+])+
([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?
([^.|'|# |!])
以下是对它有什么问题的描述...... :)
第一行 - 您在字符类中重复"
,无需转义/
第二行 - 好的,除了我不确定您使用(s)?
部分之后的情况,因为您无论如何都要在之前的群组中使用https。
第三行 - 你知道你有一个角色课吗?量词不起作用。您可能需要(\w+?\.\w+)+
。 (那是Java字符串中的(\\w+?\\.\\w+)+
。)
第四行 - 哇,逃脱了很多!!几乎都是不必要的。这样做:([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)?
(并再次:([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?
)
第五行 - 交替在角色类中没有做任何事情。这样做:[^.'#!]
,如果你真的想防止管道字符在那里,可以添加一个|
。
将所有这些评论放在一起提供了这个正则表达式:
(?<![="/>])
(www\.|(http|https|ftp|news|file)://)
(\w+?\.\w+)+
([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)?
([^.'# !])
或者,再一次,逃避Java:
(?<![=\"/>])
(www\\.|(http|https|ftp|news|file)://)
(\\w+?\\.\\w+)+
([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?
([^.'# !])
注意这是多么简单!
返回单行给出:
(?<![="/>])(www\.|(http|https|ftp|news|file)://)(\w+?\.\w+)+([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)?([^.'# !])
或
(?<![=\"/>])(www\\.|(http|https|ftp|news|file)://)(\\w+?\\.\\w+)+([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?([^.'# !])
但是我坚持使用多线 - 只是plonk (?x)
一开始它是一个有效的正则表达式,它忽略了空格,你可以使用#s进行评论 - 对于正则表达式总是一件好事只要这个!
答案 1 :(得分:4)
看起来您需要一个回调函数,它返回一个动态结果,而不是您当前在replaceAll()
中使用的固定字符串。
我想你可以从这个问题的接受答案中做出一些事情:Java equivalent to PHP's preg_replace_callback
。