Найти все ссылки в тексте, исключая тег <a>

296
21 сентября 2017, 16:59

Добрый вечер! Есть регулярка для определения ссылок в тексте:

preg_match_all('/(https?:\/\/)?([\w\.\-\_]+)\.(com|net|org|edu|gov|biz|info|name|ru|ua|рф|[a-z]{2,6}\.?)(\/[\w\.\&\?\=\-\_\:]*)*\/?/', $text, $externalURLs);

Как мне исключить ссылки, которые находятся в теге <a[href]> одним регулярным выражением?

Добавляю (?!href="([^"]+)) - не хочет работает

Answer 1

Берём регулярку из https://ru.stackoverflow.com/a/594686/178988

/(https?:\/\/|ftp:\/\/|www\.)((?![.,?!;:()]*(\s|$))[^\s]){2,}/gi

и выкидываем те, которые в href

(?<!href\s*=\s*["'],)

Получается так:

/(?<!href\s*=\s*["']?)(https?:\/\/|ftp:\/\/|www\.)((?![.,?!;:()]*(\s|$))[^\s]){2,}/gi
Answer 2

Для понимания использования конструкций вида (?<!...) и (?!...) я написал шаблон с использованием модификатора x. Благодаря этому стало возможным расставить комментарии внутри regex-шаблонов. В этом примере будут найдены две ссылки :

  1. httрs://ru.stackoverflow.com/a/594686/178988
  2. httрs://ru.stackoverflow.com/a/594686/178988

Ссылка внутри html-тега будет проигнорирована.

Примечание: символ ^ в комментариях ниже указывает на совпавшую позицию в тексте

Коммент. №1: негативная ретроспективная проверка. Совпадает с ПОЗИЦИЕЙ в тексте, слева от которой отсутствует подстрока href="^

Коммент. №2: ищет вхождения url-адресов, которые могут начинаться с протоколов http или https, за которыми обязательно следуют символы :// после которых следуют любые символы, кроме пробела. Пробел означает конец url-адреса (url-адреса не содержат пробелов).

Коммент. №3: негативная опережающая проверка. Совпадает с ПОЗИЦИЕЙ в тексте, справа от которой отсутствует подстрока ^">

$text = 'Будут найдены две ссылки : 
1. https://ru.stackoverflow.com/a/594686/178988 
2. https://ru.stackoverflow.com/a/594686/178988 
А ссылка внутри html-тега будет проигнорирована : 
<a href="http://htmlbook.ru/example/knob.html">Ссылка</a>';
$patt = '~
    (?<!href=")      # Коммент. №1
        https?://\S+ # Коммент. №2
    (?!">)           # Коммент. №3
~x';
preg_match_all($patt, $text, $arr);
var_dump($arr);

Демо

READ ALSO
Разбить результат на тэги

Разбить результат на тэги

Подскажите, пожалуйста, как решить задачу: Есть результат в одну строку:

223
php закрытие / слэш

php закрытие / слэш

Доброго вечера как бы правильно сделать

246
Инициализация вектора в структуре

Инициализация вектора в структуре

Есть такая структура:

315