URL替换为锚,而不是替换现有的锚

时间:2013-09-27 21:37:23

标签: javascript regex

我正在构建代码匹配并替换几种类型的模式(bbCode)。我正在努力做的一个匹配是[url = http:example.com]用锚链接取代所有。我也试图匹配并用锚链接替换纯文本URL。而这两者的结合是我遇到麻烦的地方。

由于我的例程是递归的,匹配并替换每个运行的整个文本,我无法替换已经包含在锚点中的URL。

这是我正在运行的递归例程:

if(text.search(p.pattern) !== -1) {
    text = text.replace(p.pattern, p.replace);
}

到目前为止,这是我对普通网址的正则表达式:

/(?!href="|>)(ht|f)tps?:\/\/.*?(?=\s|$)/ig

网址可以以http或https或ftp或ftps开头,之后包含任何文字,以空格或标点符号结尾(./!/?/,)

为了绝对清楚,我正在使用它作为匹配的测试:

应匹配:

不匹配

  • < a href =“http://www.example.com”> http://www.example.com< / a>
  • < a href =“http://www.example.com/test”> http://www.example.com/test< / a>
  • < a href =“http://example.com/test”> http://example.com/test< / a>
  • &lt; a href =“www.example.com/test”&gt; www.example.com/test< / a&gt;

我真的很乐意接受我能得到的任何帮助。

修改 以下jkshah首先接受的解决方案确实存在一些缺陷。例如,它将匹配

<img src="http://www.example.com/test.jpg">
然而,杰瑞的解决方案中的评论确实让我想再次尝试,而且该解决方案也解决了这个问题。因此我接受了这个解决方案。谢谢大家对此的帮助。 :)

3 个答案:

答案 0 :(得分:3)

也许是这样的?

/(?:(?:ht|f)tps?:\/\/|www)[^<>\]]+?(?![^<>\]]*([>]|<\/))(?=[\s!,?\]]|$)/gm

然后在最后修剪点数。

regex101 demo

虽然如果链接包含更多标点符号,但可能会导致一些问题...我会建议首先捕获链接,然后删除第二次替换的尾随标点符号。

[^<>\]]+将匹配除<>]

之外的所有字符

(?![^<>\]]*([>]|<\/))阻止匹配html标记之间的链接。

(?=[\s!,?\]]|$)用于标点符号和空格。

答案 1 :(得分:1)

以下正则表达式应该可行。它会为您的样本输入提供所需的结果。

/((?:(?:ht|f)tps?:\/\/|www)[^\s,?!]+(?!.*<\/a>))/gm

在行动here

中查看

(?!.*<\/a>) - 锚点的预示性

匹配内容将存储在$1中,可用于替换字符串。

修改

要使用<img src ..以下内容不匹配,可以使用

(^(?!.*<img\s+src)(?:(?:ht|f)tps?:\/\/|www)[^\s,?!]+(?!.*<\/a>))

答案 2 :(得分:0)

p.replace能成为一种功能吗?如果是的话:

var text = 'http://www.example.com \n' +
           'http://www.example.com/test \n' +
           'http://example.com/test \n' +
           'www.example.com/test \n' +
           '<a href="http://www.example.com">http://www.example.com </a>\n' +
           '<a href="http://www.example.com/test">http://www.example.com/test </a>\n' +
           '<a href="http://example.com/test">http://example.com/test </a>\n' +
           '<a href="www.example.com/test">www.example.com/test </a>';
var p = {
    flag: true,
    pattern: /(<a[^<]*<\/a>)|((ht|f)tps?:\/\/|www\.).*?(?=\s|$)/ig,
    replace: function ($0, $1) {
                 if ($1) {
                     return $0;
                 } else {
                     p.flag = true;
                     return "construct replacement string here";
                 }
    }
};
while(p.flag){
    p.flag = false;
    text = text.replace(p.pattern, p.replace);
}

我添加的正则表达式部分是(<a[^<]*<\/a>)|来检查url是否在锚点内的任何位置,如果是,那么替换函数会忽略它。

如果您想避免<a href="...">内的网址,但要替换其中的其他网址,请将(<a[^<]*<\/a>)|更改为(<a[^>]*>)|