Regex для соответствия URL, за которым не следует "или - PullRequest
1 голос
/ 14 апреля 2011

Я пытаюсь изменить регулярное выражение для сопоставления URL в http://daringfireball.net/2010/07/improved_regex_for_matching_urls, чтобы оно не совпадало с тем, что уже является частью действительного тега URL или используется в качестве текста ссылки.

Например, в следующей строке я хочу соответствовать http://www.foo.com,, но НЕ http://www.bar.com или http://www.baz.com

www.foo.com <a href="http://www.bar.com">http://www.baz.com</a>

Я пытался добавить отрицательный прогноз, чтобы исключить совпадения с последующим "или <, но по какой-то причине он применяется только к" m "в .com. Так что это регулярное выражение по-прежнему возвращает <a href="http://www.bar.co" rel="nofollow">http://www.bar.co http://www.baz.co как совпадения.

Я не вижу, что я делаю неправильно ... есть идеи?

\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))(?!["<])

Вот и более простой пример:

((((ht|f)tps?:\/\/)|(www.))[a-zA-Z0-9_\-.:#/~}?]+)(?!["<])

Ответы [ 2 ]

2 голосов
/ 14 апреля 2011

Я рассмотрел эту проблему в прошлом году и разработал решение, на которое вы, возможно, захотите взглянуть - см .: URL Linkification (HTTP / FTP) Эта ссылка является тестовой страницей для решения Javascript со многими примерами. трудных для ссылки URL.

Мое решение для регулярных выражений, написанное как для PHP, так и для Javascript, - не простое (но проблема, как выясняется, тоже). Для получения дополнительной информации я бы рекомендовал также прочитать:

Проблема с URL Джеффом Этвудом и
Улучшенный либеральный, точный шаблон регулярных выражений для сопоставления URL от Джона Грубера

Комментарии, следующие за сообщением в блоге Джеффа, должны быть прочитаны, если вы хотите сделать это правильно ...

Также обратите внимание, что регулярное выражение Джона Грубера содержит компонент, который может войти в область катастрофического возврата (часть, которая соответствует одному уровню соответствующих скобок).

1 голос
/ 15 апреля 2011

Да, это действительно тривиально, чтобы заставить его работать, если вы просто хотите исключить завершающие символы, просто сделайте свое выражение «независимым», тогда в этом сегменте не будет возврата.

(?>\b ...)(?!["<])

Тест Perl:

use strict;
use warnings;

my $str = 'www.foo.com <a href="http://www.bar.com">http://www.baz.com</a>http://www.some.com';

while ($str =~ m~
 (?>
    \b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))
 )
 (?!["<])
~xg)
{
   print "$1\n";
}

Выход:

www.foo.com
http://www.some.com

...