Как заменить простые URL ссылками?


454

Я использую функцию ниже, чтобы сопоставить URL-адреса внутри данного текста и заменить их для ссылок HTML. Регулярное выражение работает отлично, но в настоящее время я заменяю только первое совпадение.

Как я могу заменить все URL? Я думаю, что я должен использовать команду exec , но я не совсем понял, как это сделать.

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/i;
    return text.replace(exp,"<a href='$1'>$1</a>"); 
}

Ответы:


351

Прежде всего, использование собственного регулярного выражения для анализа URL-адресов - ужасная идея . Вы должны представить, что это достаточно распространенная проблема, согласно которой кто-то написал, отладил и протестировал библиотеку для нее, согласно RFC . URI сложны - проверьте код для разбора URL в Node.js и на странице Википедии о схемах URI .

Существует множество крайних случаев, когда речь идет о парсинге URL: международные доменные имена , фактические ( .museum) и несуществующие ( .etc) TLD, странные знаки препинания, включая скобки , знаки препинания в конце URL, имена хостов IPV6 и т. Д.

Я посмотрел на тонну в библиотеках , и есть несколько стоит использовать , несмотря на некоторые минусы:

Библиотеки, которые я быстро дисквалифицировал для этой задачи:

Если вы настаиваете на регулярном выражении, наиболее полным является регулярное выражение URL-адреса от Компонента , хотя оно будет ложно обнаруживать некоторые несуществующие двухбуквенные ДВУ, просматривая его.


3
Жаль, что URL regexp from Componentне прокомментировали, какое-то объяснение того, что он делает, было бы полезно. Autolinker.jsочень хорошо прокомментирован и имеет тесты. urlize.jsБиблиотека связана в ответе Vebjørn Ljosa в тоже выглядит и функциональной хорошо поддерживаются, хотя он не имеет тестов.
Сэм Хаслер

1
Regex101.com автоматически «объясняет» регулярное выражение, но удачи в этом :) Я также быстро нашел случай сбоя с неверным TLD (та же ссылка).
Дан Даскалеску

1
@SamHasler: Autolinker необходимо улучшить в области TLD и IDN. Добавлены некоторые тесты .
Дан Дакалеску

2
Любопытно, что никто не упомянул усилия Джона Грубера по поддержанию шаблона регулярных выражений URL . Это не единственное / идеальное решение проблемы, но в любом случае стоит разобраться, если вы предлагаете собственное решение. Просто хотел добавить это как ссылку.
oelna

2
@DanDascalescu Посмотрите на эту markdown-it.github.io/linkify-it . Эта библиотека ориентирована ровно на одну задачу - обнаружение шаблонов ссылок в тексте. Но я надеюсь, это хорошо. Например, он имеет правильную поддержку юникода, включая астральные символы. И это поддерживает международные TLD.
Виталий

285

Замена URL-адресов ссылками (Ответ на общую проблему)

Регулярное выражение в вопросе пропускает множество крайних случаев. При обнаружении URL-адресов всегда лучше использовать специализированную библиотеку, которая обрабатывает международные доменные имена, такие как новые TLD .museum, круглые скобки и другие знаки препинания внутри и в конце URL-адреса и многие другие крайние случаи. См. Сообщение в блоге Джеффа Этвуда « Проблема с URL» для объяснения некоторых других проблем.

Лучшее резюме согласующих библиотек URL в Ответ Dan Dăscălescu в+100
(по состоянию на февраль 2014 года)


«Сделать регулярное выражение заменяющим более одного совпадения» (ответ на конкретную проблему)

Добавьте «g» в конец регулярного выражения, чтобы включить глобальное сопоставление:

/ig;

Но это только исправляет проблему в вопросе, где регулярное выражение заменяло только первое совпадение. Не используйте этот код.


150

Я сделал несколько небольших модификаций в коде Трэвиса (просто чтобы избежать ненужного переобъявления - но он отлично работает для моих нужд, так что отличная работа!):

function linkify(inputText) {
    var replacedText, replacePattern1, replacePattern2, replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}

1
Как отредактировать этот код, чтобы не навредить встроенным объектам и фреймам .. (встроенные объекты YouTube и
фреймамам

5
В коде есть ошибка, которая соответствует адресам электронной почты здесь. [a-zA-Z]{2,6}следует прочитать что-то вроде строки (?:[a-zA-Z]{2,6})+, чтобы соответствовать более сложным доменным именам, например, email@example.co.uk.
Рошамбо

1
Я столкнулся с некоторыми проблемами; сначала просто http: // или http: // www (без пробела www, даже SO, по-видимому, анализирует это неправильно) создаст ссылку. И ссылки с http: // www. домен . com (без пробелов) создаст одну пустую ссылку, а затем одну с прикрепленным тегом закрытия якоря в поле href.
Альфред

1
А как насчет URL без http://или www? Будет ли это работать для таких URL?
Натан

2
Я попытался отредактировать исходное сообщение, чтобы исправить проблему mailto, но мне нужно добавить как минимум 6 символов для редактирования. Но если вы измените эту строку: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;это replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;
исправит

70

Сделал некоторые оптимизации для Linkify()кода Трэвиса выше. Я также исправил ошибку, из-за которой адреса электронной почты с форматами субдоменов не совпадали (например, example@domain.co.uk).

Кроме того, я изменил реализацию для создания прототипа Stringкласса, чтобы элементы могли быть сопоставлены следующим образом:

var text = 'address@example.com';
text.linkify();

'http://stackoverflow.com/'.linkify();

Во всяком случае, вот сценарий:

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern, '<a href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a href="mailto:$&">$&</a>');
    };
}

Лучшее на мой взгляд, поскольку функции Prototype делают вещи намного чище :)
MRVDOG

кажется, он не работает с такими адресами электронной почты: info@some-thing.com some.thing@example.com и т. д.
Марко Гальярди,

@MarcoGagliardi Хороший улов. Исправлена.
Рошамбо

1
Это не работает для строки "git clone aaaa@bitbucket.org/ooo/bbb-cc-dd.git ". Он разбил строку на куски и создал несколько якорей, таких как «git clone <a href="https://<a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> / ooo / bbb-cc-dd.git "> https: // <a href="mailto:aaaa@bitbucket.org"> aaaa@bitbucket.org </a> /ooo/bbb-cc-dd.git </a> "
Джебин

1
Это не работает с +именами пользователей электронной почты, такими как foo+bar@domain.com. Я исправил это с помощью шаблона электронной почты /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(обратите внимание на +первые скобки), но я не знаю, нарушает ли это что-то еще.
Дчаке

24

Спасибо, это было очень полезно. Я также хотел что-то, что связывало бы вещи, которые выглядели бы как URL - в качестве основного требования, это связывало бы что-то вроде www.yahoo.com, даже если префикс протокола http: // отсутствовал. Так что в основном, если "www." присутствует, это свяжет это и предположит, что это http: //. Я также хотел, чтобы электронные письма превратились в ссылки mailto :. ПРИМЕР: www.yahoo.com будет преобразован в www.yahoo.com

Вот код, с которым я закончил (комбинация кода с этой страницы и других вещей, которые я нашел в Интернете, и других вещей, которые я сделал самостоятельно):

function Linkify(inputText) {
    //URLs starting with http://, https://, or ftp://
    var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with www. (without // before it, or it'd re-link the ones done above)
    var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    var replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links
    var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
    var replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText
}

Во 2-й замене часть (^ | [^ /]) заменяет www.whever.com только в том случае, если перед ней еще нет префикса //, чтобы избежать двойной ссылки, если URL-адрес уже был связан в первой замене. Также возможно, что www.whever.com может находиться в начале строки, что является первым условием «или» в этой части регулярного выражения.

Это может быть интегрировано как плагин jQuery, как проиллюстрировано выше Джесси Р - но я специально хотел, чтобы обычная функция не действовала на существующий элемент DOM, потому что я беру текст, который у меня есть, и затем добавляю его в DOM, и Я хочу, чтобы текст был «связан» перед его добавлением, поэтому я пропускаю текст через эту функцию. Работает отлично.


1
Существует проблема со вторым шаблоном, который сам по себе соответствует простому «www.domain.com». Проблема существует, когда в URL есть какой-то реферер, например: & location = http% 3A% 2F% 2Fwww.amazon.com% 2FNeil-Young% 2Fe% 2FB000APYJWA% 3Fqid% 3D1280679945% 26sr% 3D8-2-ent & tag = tra0c7 -20 & linkCode = ur2 & camp = 1789 & creative = 9325 - в этом случае ссылка автоматически связывается снова. Быстрое решение состоит в том, чтобы добавить символ «f» после отрицательного списка, который содержит «/». Итак, выражение: replacePattern2 = /(^|[^\/f])(www\.[\S]+(\b|$))/gim
Redtopia

Приведенный выше код провалит много тестов для крайних случаев. При обнаружении URL-адресов лучше полагаться на специализированную библиотеку. Вот почему .
Дан Даскалеску

2
Я просто запустил его в строке, где некоторые веб-ссылки уже содержат ссылки href. В этом случае не удается испортить существующие рабочие ссылки.
AdamJones

17

Определить URL сложно, потому что они часто окружены знаками препинания, а пользователи часто не используют полную форму URL. Существует много функций JavaScript для замены URL гиперссылками, но я не смог найти такую, которая бы работала так же хорошо, как urlizeфильтр в основанной на Python веб-среде Django. Поэтому я перенес urlizeфункцию Django на JavaScript:

https://github.com/ljosa/urlize.js

Пример:

urlize('Go to SO (stackoverflow.com) and ask. <grin>', 
       {nofollow: true, autoescape: true})
=> "Go to SO (<a href="http://stackoverflow.com" rel="nofollow">stackoverflow.com</a>) and ask. &lt;grin&gt;"

Второй аргумент, если он истинный, вызывает rel="nofollow"вставку. Третий аргумент, если он истинный, экранирует символы, которые имеют особое значение в HTML. Смотрите файл README .


Также работает с источником HTML, таким как: www.web.com <a href = "https: // github. Com"> url </ a> некоторый текст
Паулюс Залиадуонис

@Paulius: если вы установите опцию django_compatibleв false, он будет лучше обрабатывать этот вариант использования.
Вебьорн Льоса

Django urlizeне поддерживает TLD должным образом (по крайней мере, порт JS на GitHub). Библиотека, которая правильно обрабатывает TLD, - это JavaScript Linkify Бена Алмана .
Дан Даскалеску

Добавлена ​​поддержка обнаружения URL-адресов с дополнительными доменами верхнего уровня, даже если URL-адрес не начинается с «http» или «www».
Вебьорн Лёса

10

Я внес изменения в Roshambo String.linkify () в emailAddressPattern для распознавания адресов aaa.bbb. @ Ccc.ddd.

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses *** here I've changed the expression ***
        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return this
            .replace(urlPattern, '<a target="_blank" href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a target="_blank" href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a target="_blank" href="mailto:$1">$1</a>');
    };
}

Приведенный выше код провалит много тестов для крайних случаев. При обнаружении URL-адресов лучше полагаться на специализированную библиотеку. Вот почему .
Дан Даскалеску

9

Я искал в Google что-нибудь новее и наткнулся на это:

$('p').each(function(){
   $(this).html( $(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a href="$1">$1</a> ') );
});

демо: http://jsfiddle.net/kachibito/hEgvc/1/

Работает очень хорошо для нормальных ссылок.


Что такое "нормальные ссылки" здесь? Посмотрите на развилку вашей демоверсии здесь: jsfiddle.net/hEgvc/27 Люди бы раскрыли непокрытое и сделали бы это простым способом. URI - не простая вещь в соответствии с RFC3986, и если вы хотите охватить только «Нормальные ссылки», я предлагаю следовать этому регулярному выражению хотя бы: ^ (([^: /? #] +):)? (// ([ ^ /? #] *)?) ([^? #] *) (? \ ([^ #] *))? (# (. *?))
Иван

2
Я имел в виду что-нибудь в этом формате http://example.com/folder/folder/folder/и https://example.org/blahт. Д. - просто ваш типичный не сумасшедший формат URL, который будет соответствовать 95-99% случаев использования. Я использую это для внутренней административной области, поэтому мне не нужно ничего необычного, чтобы ловить пограничные случаи или хэш-ссылки.
вырожден


5

Это решение работает, как и многие другие, и фактически использует то же регулярное выражение, что и одно из них, однако вместо возврата строки HTML это вернет фрагмент документа, содержащий элемент A и любые применимые текстовые узлы.

 function make_link(string) {
    var words = string.split(' '),
        ret = document.createDocumentFragment();
    for (var i = 0, l = words.length; i < l; i++) {
        if (words[i].match(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi)) {
            var elm = document.createElement('a');
            elm.href = words[i];
            elm.textContent = words[i];
            if (ret.childNodes.length > 0) {
                ret.lastChild.textContent += ' ';
            }
            ret.appendChild(elm);
        } else {
            if (ret.lastChild && ret.lastChild.nodeType === 3) {
                ret.lastChild.textContent += ' ' + words[i];
            } else {
                ret.appendChild(document.createTextNode(' ' + words[i]));
            }
        }
    }
    return ret;
}

Есть некоторые предостережения, а именно с более старой поддержкой IE и textContent.

вот демо


2
@DanDascalescu Вместо того, чтобы подавлять голосование, возможно, предоставьте свои упомянутые крайние случаи.
rlemon

Нужно ли мне? Взгляните на регулярное выражение компонента для URL . Но если вы настаиваете, бегите против набора тестов Бена Алмана . Я начал вносить неудачные тесты, например, для urlize , но вскоре понял, что это стоит делать только для серьезных библиотечных усилий. При всем уважении, приведенный выше ответ - StackOverflow, а не библиотека с открытым исходным кодом, пытающаяся правильно проанализировать URL-адреса.
Дан Даскалеску

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

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

1
Но как это оправдывает отрицательное голосование за каждый ответ с регулярным выражением не ваших предпочтительных решений?
rlemon

4

Если вам нужно показать более короткую ссылку (только домен), но с таким же длинным URL, вы можете попробовать мою модификацию версии кода Сэма Хаслера, опубликованную выше

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(exp, "<a href='$1' target='_blank'>$3</a>");
}

3

Reg Ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig

function UriphiMe(text) {
      var exp = /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig; 
      return text.replace(exp,"<a href='$1'>$1</a>");
}

Ниже приведены некоторые проверенные строки:

  1. Найдите меня на www.google.com
  2. WWW
  3. Найди меня на www. http://www.com
  4. Следуй за мной по: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Следуй за мной по: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Примечание: если вы не хотите передавать wwwкак действительный, просто используйте ниже reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig


Приведенный выше код провалит много тестов для крайних случаев. При обнаружении URL-адресов ВСЕГДА лучше полагаться на специализированную библиотеку. Вот почему .
Дан Даскалеску

3

Предупреждения о сложности URI должны быть записаны, но простой ответ на ваш вопрос таков:
Чтобы заменить каждое совпадение, вам нужно добавить /gфлаг в конец RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi


3
/**
 * Convert URLs in a string to anchor buttons
 * @param {!string} string
 * @returns {!string}
 */

function URLify(string){
  var urls = string.match(/(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)/g);
  if (urls) {
    urls.forEach(function (url) {
      string = string.replace(url, '<a target="_blank" href="' + url + '">' + url + "</a>");
    });
  }
  return string.replace("(", "<br/>(");
}

простой пример


2

Будь проще! Скажите, что вы не можете иметь, а не то, что вы можете иметь :)

Как упоминалось выше, URL-адреса могут быть довольно сложными, особенно после «?», И не все из них начинаются с «www». напримерmaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

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

Матч

http(s):// (anything but a space)+

www. (anything but a space)+

Где «что-нибудь» - это [^'"<>\s] ... в основном жадная спичка, в которой вы встретите пробел, цитату, угловую скобку или конец строки

Также:

Не забудьте проверить, что он еще не в формате URL, например, текст содержит href="..." илиsrc="..."

Добавить ref = nofollow (если необходимо)

Это решение не так «хорошо», как библиотеки, упомянутые выше, но намного проще и хорошо работает на практике.

if html.match( /(href)|(src)/i )) {
    return html; // text already has a hyper link in it
    }

html = html.replace( 
            /\b(https?:\/\/[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='$1'>$1</a>" 
            );

html = html.replace( 
            /\s(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

html = html.replace( 
             /^(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

return html;

2

Корректное обнаружение URL с поддержкой международных доменов и астральных символов - не тривиальная вещь linkify-itбиблиотека строит регулярные выражения из многих условий , а конечный размер составляет около 6 килобайт :). Это более точно, чем все библиотеки, на которые в настоящее время есть ссылка в принятом ответе.

Смотрите ссылку-это демо чтобы проверить все крайние случаи и проверить свои.

Если вам нужно связать исходный код HTML, вам следует сначала проанализировать его и повторить каждый текстовый токен отдельно.


1

Я написал еще одну библиотеку JavaScript, она может быть лучше для вас, поскольку она очень чувствительна к наименьшему количеству ложных срабатываний, быстрая и небольшая по размеру. В настоящее время я активно поддерживаю его, поэтому, пожалуйста, протестируйте его на демонстрационной странице и посмотрите, как он будет работать для вас.

ссылка: https://github.com/alexcorvi/anchorme.js


Потрясающая библиотека. Большое спасибо!
Сердар Değirmenci

0

Мне пришлось сделать обратное, и сделать HTML-ссылки только в URL, но я изменил ваше регулярное выражение, и это работает как шарм, спасибо :)

var exp = /<a\s.*href=['"](\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_ |:!...,;] * [- A-Z0-9 + & @ # \ /% = ~ _ |]) [ ' "] *> * <\ / а> / мкг;

source = source.replace (exp, "$ 1");

Я не вижу смысла вашего регулярного выражения. Это соответствует всему, заменяя все на все. По сути, ваш код ничего не делает.
Чад Грант

8
Думаю, мне следует подождать, чтобы оставить комментарий, чтобы люди могли закончить редактирование. Извините.
Чад Грант

0

Обнаружение электронной почты в ответе Travitron выше не сработало для меня, поэтому я расширил / заменил его следующим (код C #).

// Change e-mail addresses to mailto: links.
const RegexOptions o = RegexOptions.Multiline | RegexOptions.IgnoreCase;
const string pat3 = @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,6})";
const string rep3 = @"<a href=""mailto:$1@$2.$3"">$1@$2.$3</a>";
text = Regex.Replace(text, pat3, rep3, o);

Это позволяет использовать адреса электронной почты, такие как « firstname.secondname@one.two.three.co.uk ».


Приведенный выше код провалит много тестов для крайних случаев. При обнаружении URL-адресов ВСЕГДА лучше полагаться на специализированную библиотеку. Вот почему .
Дан Даскалеску

Спасибо, @DanDascalescu Как правило, это всегда лучше по-обобщать.
Уве Кейм

0

После ввода из нескольких источников у меня теперь есть решение, которое работает хорошо. Это было связано с написанием собственного кода замены.

Ответа на этот вопрос .

Скрипки .

function replaceURLWithHTMLLinks(text) {
    var re = /(\(.*?)?\b((?:https?|ftp|file):\/\/[-a-z0-9+&@#\/%?=~_()|!:,.;]*[-a-z0-9+&@#\/%=~_()|])/ig;
    return text.replace(re, function(match, lParens, url) {
        var rParens = '';
        lParens = lParens || '';

        // Try to strip the same number of right parens from url
        // as there are left parens.  Here, lParenCounter must be
        // a RegExp object.  You cannot use a literal
        //     while (/\(/g.exec(lParens)) { ... }
        // because an object is needed to store the lastIndex state.
        var lParenCounter = /\(/g;
        while (lParenCounter.exec(lParens)) {
            var m;
            // We want m[1] to be greedy, unless a period precedes the
            // right parenthesis.  These tests cannot be simplified as
            //     /(.*)(\.?\).*)/.exec(url)
            // because if (.*) is greedy then \.? never gets a chance.
            if (m = /(.*)(\.\).*)/.exec(url) ||
                    /(.*)(\).*)/.exec(url)) {
                url = m[1];
                rParens = m[2] + rParens;
            }
        }
        return lParens + "<a href='" + url + "'>" + url + "</a>" + rParens;
    });
}

2
Приведенный выше код (и большинство регулярных выражений в целом) не пройдёт множество тестов для крайних случаев. При обнаружении URL-адресов лучше полагаться на специализированную библиотеку. Вот почему .
Дан Даскалеску

Дэн, есть ли такая библиотека? Хотя в этом случае мы все равно соответствовали бы приведенному выше регулярному выражению, чтобы код никогда не мог выводить мусор, когда что-то вроде мусора (даже если другая библиотека сертифицирует мусор как действительный URL / URI) в качестве ввода.
Майк Местник


0

Вот мое решение:

var content = "Visit https://wwww.google.com or watch this video: https://www.youtube.com/watch?v=0T4DQYgsazo and news at http://www.bbc.com";
content = replaceUrlsWithLinks(content, "http://");
content = replaceUrlsWithLinks(content, "https://");

function replaceUrlsWithLinks(content, protocol) {
    var startPos = 0;
    var s = 0;

    while (s < content.length) {
        startPos = content.indexOf(protocol, s);

        if (startPos < 0)
            return content;

        let endPos = content.indexOf(" ", startPos + 1);

        if (endPos < 0)
            endPos = content.length;

        let url = content.substr(startPos, endPos - startPos);

        if (url.endsWith(".") || url.endsWith("?") || url.endsWith(",")) {
            url = url.substr(0, url.length - 1);
            endPos--;
        }

        if (ROOTNS.utils.stringsHelper.validUrl(url)) {
            let link = "<a href='" + url + "'>" + url + "</a>";
            content = content.substr(0, startPos) + link + content.substr(endPos);
            s = startPos + link.length;
        } else {
            s = endPos + 1;
        }
    }

    return content;
}

function validUrl(url) {
    try {
        new URL(url);
        return true;
    } catch (e) {
        return false;
    }
}

0

Попробуйте следующую функцию:

function anchorify(text){
  var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
  var text1=text.replace(exp, "<a href='$1'>$1</a>");
  var exp2 =/(^|[^\/])(www\.[\S]+(\b|$))/gim;
  return text1.replace(exp2, '$1<a target="_blank" href="http://$2">$2</a>');
}

alert(anchorify("Hola amigo! https://www.sharda.ac.in/academics/"));


0

Попробуйте ниже решение

function replaceLinkClickableLink(url = '') {
let pattern = new RegExp('^(https?:\\/\\/)?'+
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+
        '((\\d{1,3}\\.){3}\\d{1,3}))'+
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+
        '(\\?[;&a-z\\d%_.~+=-]*)?'+
        '(\\#[-a-z\\d_]*)?$','i');

let isUrl = pattern.test(url);
if (isUrl) {
    return `<a href="${url}" target="_blank">${url}</a>`;
}
return url;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.