Как заменить простые URL ссылками?
224709 просмотра
22 ответа
Я использую функцию ниже, чтобы сопоставить 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>");
}
Автор: Sergio del Amo
Источник
Размещён: 17.05.2019 02:48
Ответы (22)
306 плюса
Во-первых, использование собственного регулярного выражения для анализа URL-адресов - ужасная идея . Вы должны представить, что это достаточно распространенная проблема, согласно которой кто-то написал, отладил и протестировал библиотеку, согласно RFC . URI сложны - посмотрите код для разбора URL в Node.js и на странице Википедии о схемах URI .
Существует множество крайних случаев, когда речь идет о парсинге URL: международные доменные имена , фактические ( .museum
) или несуществующие ( .etc
) TLD, странные знаки препинания, включая скобки , знаки препинания в конце URL, имена хостов IPV6 и т. Д.
Я посмотрел на тонну в библиотеках , и есть несколько стоит использовать , несмотря на некоторые минусы:
- В Linkify Soapbox были приложены серьезные усилия, и в июне 2015 года основной рефакторинг удалил зависимость jQuery . У него все еще есть проблемы с IDN .
- AnchorMe является новичком, который утверждает, что быстрее и экономнее. Некоторые проблемы с IDN .
- Autolinker.js перечисляет функции очень конкретно (например, «Будет правильно обрабатывать ввод HTML. Утилита не будет изменять
href
атрибут внутри тегов anchor ()» ). Я добавлю несколько тестов, когда демоверсия станет доступной .
Библиотеки, которые я быстро дисквалифицировал для этой задачи:
- URL-адрес Django не обрабатывал определенные TLD должным образом (вот официальный список действующих TLD . Нет демонстрации .
- autolink-js не обнаружит «www.google.com» без http: //, поэтому он не совсем подходит для автоматического нахождения «случайных URL» (без схемы / протокола) в виде простого текста.
- Ссылка Бена Алмана не поддерживается с 2009 года.
Если вы настаиваете на регулярном выражении, наиболее полным является регулярное выражение URL-адреса от Компонента , хотя оно будет неверно обнаруживать некоторые несуществующие двухбуквенные ДВУ, просматривая его.
Автор: Dan Dascalescu Размещён: 21.02.2014 04:46284 плюса
Замена URL-адресов ссылками (Ответ на общую проблему)
Регулярное выражение в вопросе пропускает множество крайних случаев. При обнаружении URL-адресов всегда лучше использовать специализированную библиотеку, которая обрабатывает международные доменные имена, такие как новые TLD .museum
, круглые скобки и другие знаки пунктуации внутри и в конце URL-адреса и многие другие крайние случаи. См. Сообщение в блоге Джеффа Этвуда « Проблема с URL-адресами» для объяснения некоторых других проблем.
Лучшее резюме библиотек согласующих URL в Ответ Dan Dăscălescu в
(по состоянию на февраль 2014 года)
«Сделать регулярное выражение заменяющим более одного совпадения» (ответ на конкретную проблему)
Добавьте «g» в конец регулярного выражения, чтобы включить глобальное сопоставление:
/ig;
Но это только устраняет проблему в вопросе, где регулярное выражение заменяло только первое совпадение. Не используйте этот код.
Автор: Sam Hasler Размещён: 01.09.2008 10:00140 плюса
Я сделал несколько небольших модификаций в коде Трэвиса (просто чтобы избежать ненужного переобъявления - но он отлично работает для моих нужд, так что отличная работа!):
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;
}
Автор: cloud8421
Размещён: 08.10.2010 11:50
65 плюса
Сделал некоторые оптимизации для 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>');
};
}
Автор: Roshambo
Размещён: 19.08.2011 03:03
23 плюса
Спасибо, это было очень полезно. Я также хотел что-то, что связывало бы вещи, которые выглядели бы как 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, и Я хочу, чтобы текст был «связан» перед его добавлением, поэтому я пропускаю текст через эту функцию. Работает отлично.
Автор: Travis Размещён: 29.01.2010 11:5517 плюса
Определить URL сложно, потому что они часто окружены знаками препинания, а пользователи часто не используют полную форму URL. Существует много функций JavaScript для замены URL гиперссылками, но я не смог найти такую, которая бы работала так же хорошо, как urlize
фильтр в веб-фреймворке на основе Python Django. Поэтому я перенес urlize
функцию Django на JavaScript:
Пример:
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. <grin>"
Второй аргумент, если истина, вызывает rel="nofollow"
вставку. Третий аргумент, если он истинный, экранирует символы, которые имеют особое значение в HTML. Смотрите файл README .
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>');
};
}
Автор: Christian Koch
Размещён: 21.08.2011 02:15
7 плюса
Лучший скрипт для этого: http://benalman.com/projects/javascript-linkify-process-lin/
Автор: FlycKER Размещён: 25.06.2010 05:186 плюса
Я искал в 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/
Работает очень хорошо для обычных ссылок.
Автор: degenerate Размещён: 24.03.2016 02:195 плюса
Это решение работает, как и многие другие, и фактически использует то же регулярное выражение, что и одно из них, однако вместо возврата строки 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.
вот демо
Автор: rlemon Размещён: 22.11.2012 07:034 плюса
Если вам нужно показать более короткую ссылку (только домен), но с таким же длинным 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>");
}
Автор: Artjom Kurapov
Размещён: 09.12.2011 08:42
3 плюса
Предупреждения о сложности URI должны быть записаны, но простой ответ на ваш вопрос таков:
Чтобы заменить каждое совпадение, вам нужно добавить /g
флаг в конец RegEx:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi
2 плюса
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>");
}
Ниже приведены некоторые проверенные строки:
- Найдите меня на www.google.com
- WWW
- Найди меня на www. http://www.com
- Следуй за мной по: http://www.nishantwork.wordpress.com
- http://www.nishantwork.wordpress.com
- Следуй за мной по: http://www.nishantwork.wordpress.com
- https://stackoverflow.com/users/430803/nishant
Примечание: если вы не хотите передавать www
как действительный, просто используйте ниже reg ex:
/(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
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;
Автор: Andrew Murphy
Размещён: 27.05.2014 10:58
1 плюс
Корректное обнаружение URL с поддержкой международных доменов и астральных символов - не тривиальная вещь. linkify-it
библиотека строит регулярные выражения из многих условий , а конечный размер составляет около 6 килобайт :). Это более точно, чем все библиотеки, на которые в настоящее время есть ссылка в принятом ответе.
Посмотрите демоверсию linkify-it, чтобы проверить все крайние случаи и проверить свои.
Если вам нужно связать исходный код HTML, вам следует сначала проанализировать его и повторить каждый текстовый токен отдельно.
Автор: Vitaly Размещён: 16.05.2015 07:501 плюс
Я написал еще одну библиотеку JavaScript, она может быть лучше для вас, поскольку она очень чувствительна к наименьшему количеству ложных срабатываний, быстрая и небольшая по размеру. В настоящее время я активно поддерживаю его, поэтому, пожалуйста, протестируйте его на демонстрационной странице и посмотрите, как он будет работать для вас.
ссылка: https://github.com/alexcorvi/anchorme.js
Автор: Alex C. Размещён: 02.03.2016 09:260 плюса
Мне пришлось сделать обратное, и сделать HTML-ссылки только в URL, но я изменил ваше регулярное выражение, и это работает как шарм, спасибо :)
var exp = / * <\ / а> / мкг; source = source.replace (exp, "$ 1");Автор: Reece Размещён: 27.04.2009 03:20
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 ».
Автор: Uwe Keim Размещён: 12.02.2010 08:020 плюса
После ввода из нескольких источников у меня теперь есть решение, которое работает хорошо. Это было связано с написанием вашего собственного кода замены.
Скрипки .
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;
});
}
Автор: Mike Mestnik
Размещён: 04.11.2013 04:59
0 плюса
Замените URL-адреса в тексте HTML-ссылками, игнорируйте URL-адреса в теге href / pre. https://github.com/JimLiu/auto-link
Автор: Jim Liu Размещён: 11.06.2015 09:310 плюса
Вот мое решение:
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;
}
}
Автор: AndroidDev
Размещён: 24.07.2018 01:29
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/"));
Вопросы из категории :
- javascript Как определить, какой из указанных шрифтов был использован на веб-странице?
- javascript Валидация клиентской стороны ASP.Net
- javascript Длина объекта JavaScript
- javascript Получение текста из выпадающего списка
- javascript Скрипт входа со скрытыми кнопками
- javascript Как автоматически изменить размер текстовой области с помощью Prototype?
- javascript Удаление элементов с помощью Array.map в JavaScript
- javascript Прокрутка переполненных DIV с помощью JavaScript
- javascript API Карт Google - проблемы с классом GLatLngBounds
- javascript Проверка десятичных чисел в JavaScript - IsNumeric ()
- regex Learning Regular Expressions
- regex Regex и unicode
- regex Мое регулярное выражение слишком подходит. Как мне это остановить?
- regex Как выполнить подстановку Perl для строки, сохранив оригинал?
- regex Замена n-го экземпляра совпадения с регулярным выражением в Javascript
- regex Как заменить простые URL ссылками?
- regex Python re.sub с флагом не заменяет все вхождения
- regex Как проверить адрес электронной почты в JavaScript
- regex Как экранировать текст для регулярного выражения в Java
- regex Регулярное выражение, которое будет соответствовать объявлению метода Java