使用正则表达式进行条件替换

mat*_*att 2 java regex replace

当谈到正则表达式时,我是一个相对新手,但我开始掌握它.我开始在java中编写一个方法来"链接"一个字符串 - 也就是说,扫描它以获取任何url引用(即"http:// ...")或看起来像web地址的字符串("www.example. COM ...")

所以,例如,如果我有一个看起来像这样的字符串:

My favorite site is http://www.example.com.  What is yours?
Run Code Online (Sandbox Code Playgroud)

在通过该方法运行之后,您将获得一个字符串,表示:

My favorite site is <a href="http://www.example.com">http://www.example.com</a>.  What is yours?
Run Code Online (Sandbox Code Playgroud)

网上淘了一段时间后,我终于可以不同的表达,帮助我做什么我要找的(一些例子包括网址在实际的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\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?([^.|'|# |!])";

    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);
}
Run Code Online (Sandbox Code Playgroud)

还有简单的toLinkifiedString版本,它只接受字符串s - 它只调用toLinkifiedString(s,null)

就像我说的那样,这个模式正在捕捉我需要捕获的所有内容,并且replaceAll对于每种情况都很有效,除了链接以www开头.如果匹配以"www"开头而不是像"http"或"ftp"这样的协议,我想有条件地在结果链接前面加上"http://".那是:

MyClass.toLinkifiedString("go to www.example.org") 
Run Code Online (Sandbox Code Playgroud)

应该回来

go to <a href="http://www.example.com">www.example.org</a>
Run Code Online (Sandbox Code Playgroud)

匹配组如下:

  • $ 0 - 找到的实际网址:http://www.example.orgwww.example.net
  • $ 1 - 协议匹配("http://"或"www"表示没有协议的链接)

我想我想要做的是,在伪代码中是这样的:

matcher.replaceAll("<a href="(if protocol = "www", insert "http://" + url - otherwise, insert url">url</a>"
Run Code Online (Sandbox Code Playgroud)

这可能吗?或者我应该只为能够仅从以"http:// ..."开头的链接创建锚点而感到高兴:)

感谢任何人都能提供的帮助

Pet*_*ton 10

对于你的具体问题,肯定会使用Tomalak所说的回调功能.

对于所有这些斜线的问题,以及其他各种奇怪的问题......

这是您当前的Java正则表达式跨行分割:

(?<![=\"\"\\/>])
(www\\.|(http|https|ftp|news|file)(s)?://)
([\\w+?\\.\\w+])+
([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?
([^.|'|# |!])
Run Code Online (Sandbox Code Playgroud)

和非Java正则表达式相同(没有Java字符串转义):

(?<![=""\/>])
(www\.|(http|https|ftp|news|file)(s)?://)
([\w+?\.\w+])+
([a-zA-Z0-9\~\!\@\#\$\%\^\&amp;\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?
([^.|'|# |!])
Run Code Online (Sandbox Code Playgroud)


以下是对它有什么问题的描述...... :)

第一行 - 你"在字符类中重复,不需要逃避/

第二行 - 好的,除了我不确定你在使用该(s)?部件之后是什么,因为你在前一组中都有https.

第三行 - 你知道你有一个角色课吗?量词不起作用.你可能想要(\w+?\.\w+)+.(那是(\\w+?\\.\\w+)+在Java字符串中.)

第四行 - 哇,逃脱了多少!! 几乎都是不必要的.这给一去:([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)? (并再次:([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?)

第五行 - 交替在字符类中不做任何事情.如果您确实想要防止管道char出现在那里,那么这样做:[^.'#!]并添加一个|.

将所有这些评论放在一起提供了这个正则表达式:

(?<![="/>])
(www\.|(http|https|ftp|news|file)://)
(\w+?\.\w+)+
([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)?
([^.'# !])
Run Code Online (Sandbox Code Playgroud)

或者,再次,逃避Java:

(?<![=\"/>])
(www\\.|(http|https|ftp|news|file)://)
(\\w+?\\.\\w+)+
([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?
([^.'# !])
Run Code Online (Sandbox Code Playgroud)

注意那是多么简单!

回到一行就可以了:

(?<![="/>])(www\.|(http|https|ftp|news|file)://)(\w+?\.\w+)+([a-zA-Z0-9~!@#$%^&*()_\-=+\/?.:;',]*)?([^.'# !])
Run Code Online (Sandbox Code Playgroud)

要么

(?<![=\"/>])(www\\.|(http|https|ftp|news|file)://)(\\w+?\\.\\w+)+([a-zA-Z0-9~!@#$%^&*()_\\-=+\\/?.:;',]*)?([^.'# !])
Run Code Online (Sandbox Code Playgroud)

但是我坚持使用多线 - 只是(?x)在一开始就是plonk ,这是一个有效的正则表达式,它忽略了空格,你可以使用#s进行评论 - 只要有这个就一直是正则表达式的好东西!