通过带有正则表达式的链接替换字符串中的多个URL

时间:2013-12-02 16:15:04

标签: regex angularjs url

我正在使用带有AngularJS的过滤器来替换window.open()函数中的URL以及mailto中的电子邮件:

app.filter('parseUrl', function() {

        //URLs starting with http://, https://, or ftp://
        var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;

        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        //Change email addresses to mailto:: links.
        var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;

        return function(text, target, otherProp) {  
            var originText = text;
            if(text == undefined || text == "") {
                return "";
            } else {      
                angular.forEach(text.match(replacePattern1), function(url) {
                    text = text.replace(replacePattern1, "<span onclick=\"window.open('$1', '_system');\" class='link_url'>$1</span>");
                });
                angular.forEach(text.match(replacePattern2), function(url) {
                    text = text.replace(replacePattern2, "<span onclick=\"window.open('http://$2', '_system');\" class='link_url'>$1$2</span>");
                });
                angular.forEach(text.match(replacePattern3), function(url) {
                    text = text.replace(replacePattern3, "<a href=\"mailto:$1\">$1</a>");
                });

                return text;     
            }  
        };
});

它适用于一个URL或一个电子邮件,但是当我有两个或更多URL时它不起作用,因为它用一个带有window.open()函数的span替换多次URL。正如您在JSFiddle中看到的那样:http://jsfiddle.net/wps94/1/

你有想法避免这种情况吗?也许通过改变正则表达式?

谢谢

2 个答案:

答案 0 :(得分:2)

尝试使用单个正则表达式和替换函数:

var replacePattern = /\b((http:\/\/|https:\/\/|ftp:\/\/|mailto:|news:)|www\.|ftp\.|[^ \,\;\:\!\)\(\""\'\<\>\f\n\r\t\v]+@)([^ \,\;\:\!\)\(\""\'\<\>\f\n\r\t\v]+)\b/gim;

return function(text, target, otherProp) {  
   var originText = text;
   if(text == undefined || text == "") {
      return "";
   } else {
      return text.replace(replacePattern, function($0, $1) {
         var match = $0;
         var protocol = $1;

         if ((/^www\./i).test(match))
         {
            return "<span onclick=\"window.open('http://" + match + "', '_system');\" class='link_url'>" + match + "</span>";
         }
         if ((/^ftp\./i).test(match))
         {
            return "<span onclick=\"window.open('ftp://" + match + "', '_system');\" class='link_url'>" + match + "</span>";
         }

         if (protocol && protocol.charAt(0) === '@')
         {
            return "<a href=\"mailto:" + match + "\">" + match + "</a>";
         }

         return "<span onclick=\"window.open('" + match + "', '_system');\" class='link_url'>" + match + "</span>";
      });
   }  
};

http://jsfiddle.net/wps94/2/

答案 1 :(得分:1)

forEach中,将text =更改为newText =,然后将其返回......就像这样:

app.filter('parseUrl', function() {

    //URLs starting with http://, https://, or ftp://
    var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

    //Change email addresses to mailto:: links.
    var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;

    return function(text, target, otherProp) {  
        var originText = text;
        if(text == undefined || text == "") {
            return "";
        } else {    
            var newText;

            angular.forEach(text.match(replacePattern1), function(url) {
                newText = text.replace(replacePattern1, "<span onclick=\"window.open('$1', '_system');\" class='link_url'>$1</span>");
            });
            angular.forEach(text.match(replacePattern2), function(url) {
                newText = text.replace(replacePattern2, "<span onclick=\"window.open('http://$2', '_system');\" class='link_url'>$1$2</span>");
            });
            angular.forEach(text.match(replacePattern3), function(url) {
                newText = text.replace(replacePattern3, "<a href=\"mailto:$1\">$1</a>");
            });

            return newText;     
        }  
    };
});

forEach的每次传递都在查看text的值,并且已经为第一个网址而不是初始值进行了替换。