Нужно хорошее регулярное выражение для преобразования URL-адресов в ссылки, но оставить только существующие ссылки

У меня загружен контент, представленный пользователями. Это HTML и может содержать URL-адреса. Некоторые из них будут уже (если пользователь хорош), но иногда пользователи ленивы и просто набирают www.something.com или в лучшем случае http://www.something.com .

Я не могу найти приличное регулярное выражение для захвата URL-адресов, но игнорировать те, которые сразу справа от двойной кавычки или «>». Кто-нибудь получил?

    Jan Goyvaerts, создатель RegexBuddy , написал ответ на блог Джеффа Этвуда, в котором рассматриваются проблемы, которые Джефф использовал и предлагает хорошее решение.

     \b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#/%=~_|$?!:,.]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#/%=~_|$] 

    Чтобы игнорировать совпадения, которые встречаются прямо рядом с «или», вы можете добавить (?< ![">]) В начало регулярного выражения, чтобы вы

     (?< ![">])\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#/%=~_|$?!:,.]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#/%=~_|$] 

    Это будет соответствовать полным адресам ( http: // … ) И адресам, начинающимся с www. или ftp. – вам не повезло с такими адресами, как ars.userfriendly.org …

    Эта ветка старая, как холмы, но я столкнулся с ней, работая над собственной проблемой: то есть, конвертирует любые URL-адреса в ссылки, но оставляю в покое все, которые уже находятся в якорных тегах. Через некоторое время это то, что вышло:

     (?!(?!.*?)(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$?!:,.]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$] 

    Со следующим вводом:

     ○○@https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0$@○○ http://google.com https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/www.google.com 

    ○○@https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0$@○○

    this is a normal sentence. let's hope it's ok. https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/www.google.com

    Это результат preg_replace:

     ○○@https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0$@○○ http://google.com https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/www.google.com 

    ○○@https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0$@○○

    this is a normal sentence. let's hope it's ok. https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/www.google.com

    Просто хотел внести свой вклад, чтобы спасти кого-нибудь.

    Я внесла небольшое изменение в регулярное выражение, содержащееся в исходном ответе:

     (?< ![.*">])\b(?:(?:https?|ftp|file)://|[az]\.)[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$?!:,.]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$] 

    который позволяет больше поддоменов, а также выполняет более полную проверку тегов. Чтобы применить это к замене preg PHP, вы можете использовать:

     $convertedText = preg_replace( '@(?< ![.*">])\b(?:(?:https?|ftp|file)://|[az]\.)[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$?!:,.]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&#/%=~_|$]@i', '\https://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0', $originalText ); 

    Заметьте, я удалил @ из регулярного выражения, чтобы использовать его как разделитель для preg_replace. Довольно редко, что @ будет использоваться в URL-адресе в любом случае.

    Очевидно, вы можете изменить заменяющий текст и удалить target = “_ blank” или добавить rel = “nofollow” и т. Д.

    Надеюсь, это поможет.

     if (preg_match('/\b(?< !=")(https?|ftp|file):\/\/[-A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#\/%?=~_|!:,.;]*[A-Zhttps://stackoverflow.com/questions/287144/need-a-good-regex-to-convert-urls-to-links-but-leave-existing-links-alone/0-9+&@#\/%=~_|](?!.*".*>)(?!.*< \/a>)/i', $subject)) { # Successful match } else { # Match attempt failed } 

    Бесстыдный плагин: вы можете посмотреть здесь ( регулярное выражение заменить слово по ссылке ) для вдохновения.

    Вопрос просил заменить какое-то слово определенной ссылкой, если там уже не было ссылки. Таким образом, проблема, которую вы имеете, более или менее то же самое.

    Все, что вам нужно, это регулярное выражение, которое соответствует URL-адресу (вместо слова). Простейшее предположение было бы следующим: URL (необязательно) начинается с "http://" , "ftp://" или "mailto:" и длится до тех пор, пока не будут символы пробела, разрывы строк, тег скобки или кавычки).

    Остерегайтесь длинного регулярного выражения. Применяйте регистр без учета регистра.

     (href\s*=\s*['"]?)?((?:http://|ftp://|mailto:)?[^.,<>"'\s\r\n\t]+(?:\.(?![.<>"'\s\r\n])[^.,!<>"'\s\r\n\t]+)+) 

    Будьте предупреждены – это также будет соответствовать URL-адресам, которые являются технически недействительными, и он распознает things.formatted.like.this как URL-адрес. Это зависит от ваших данных, если они слишком нечувствительны. Я могу точно настроить регулярное выражение, если у вас есть примеры, где он возвращает ложные срабатывания.

    Регулярное выражение создаст две группы совпадений. Группа 2 будет содержать сопоставленную вещь, которая, скорее всего, является URL-адресом. Группа 1 будет содержать пустую строку или 'href="' . Вы можете использовать ее как индикатор того, что это совпадение произошло внутри параметра href существующей ссылки, и вам не нужно касаться этого.

    Как только вы подтвердите, что это делает для вас большую часть времени (с предоставленными пользователем данными, вы никогда не можете быть уверены), вы можете сделать все остальное в два этапа, как я предложил в другом вопросе:

    1. Создайте ссылку вокруг каждого URL-адреса ( если в команде 1 есть что-то)! Это приведет к двойным вложенным тегам для вещей, у которых уже есть ссылка.
    2. Сканировать неверно вложенные tags , удаляя самую внутреннюю

    Чтобы пропустить существующие, просто используйте look-behind-add (?< !href=") в начало вашего регулярного выражения, чтобы оно выглядело примерно так:

     /(?< !href=")http://\S*/ 

    Очевидно, что это не полное решение для поиска всех типов URL-адресов, но это должно решить вашу проблему возиться с существующими.