Wie ersetze ich einfache URLs durch Links?


453

Ich verwende die folgende Funktion, um URLs in einem bestimmten Text abzugleichen und sie durch HTML-Links zu ersetzen. Der reguläre Ausdruck funktioniert hervorragend, aber derzeit ersetze ich nur das erste Spiel.

Wie kann ich die gesamte URL ersetzen? Ich denke, ich sollte den Befehl exec verwenden , aber ich habe nicht wirklich herausgefunden, wie es geht.

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>"); 
}

Antworten:


350

Zunächst einmal ist es eine schreckliche Idee , Ihren eigenen regulären Ausdruck zu rollen, um URLs zu analysieren . Sie müssen sich vorstellen, dass dies ein häufig genug auftretendes Problem ist , bei dem laut RFCs jemand eine Bibliothek dafür geschrieben, debuggt und getestet hat . URIs sind komplex - lesen Sie den Code für die URL-Analyse in Node.js und auf der Wikipedia-Seite zu URI-Schemata .

Es gibt eine Menge Randfälle beim Parsen von URLs: internationale Domainnamen , tatsächliche ( .museum) vs. nicht vorhandene ( .etc) TLDs, seltsame Interpunktion einschließlich Klammern , Interpunktion am Ende der URL, IPV6-Hostnamen usw.

Ich habe bei sah eine Tonne von Bibliotheken , und es gibt ein paar wert trotz einiger Nachteile mit:

Bibliotheken, die ich für diese Aufgabe schnell disqualifiziert habe:

Wenn Sie auf einem regulären Ausdruck bestehen, ist der URL-Regexp von Component am umfassendsten , obwohl er einige nicht vorhandene TLDs mit zwei Buchstaben fälschlicherweise erkennt , wenn Sie ihn betrachten.


3
Es ist schade, dass das URL regexp from Componentnicht kommentiert wird. Eine Erklärung dessen, was es tut, wäre hilfreich. Autolinker.jsist sehr gut kommentiert und hat Tests. Die urlize.jsBibliothek, auf die in der Antwort von Vebjorn Ljosa verwiesen wird, sieht ebenfalls gut aus und ist gut gepflegt, obwohl sie keine Tests enthält.
Sam Hasler

1
Regex101.com "erklärt" automatisch den regulären Ausdruck, aber viel Glück damit :) Ich habe auch schnell einen Fehlerfall mit einer ungültigen TLD gefunden (gleicher Link).
Dan Dascalescu

1
@SamHasler: Autolinker muss im Bereich TLDs und IDNs verbessert werden. Einige Tests hinzugefügt .
Dan Dascalescu

2
Neugierig, dass niemand John Grubers Bemühungen zur Aufrechterhaltung eines regulären Regex-Musters erwähnte . Es ist nicht die einzige / ideale Lösung für das Problem, aber auf jeden Fall eine Untersuchung wert, wenn Sie Ihre eigene Lösung entwickeln. Ich wollte dies nur als Referenz hinzufügen.
Oelna

2
Werfen Sie einen Blick auf diese @DanDascalescu markdown-it.github.io/linkify-it . Diese Bibliothek konzentriert sich genau auf eine Aufgabe - das Erkennen von Verknüpfungsmustern im Text. Aber ich hoffe, es macht es gut. Zum Beispiel hat es die richtige Unicode-Unterstützung, einschließlich Astralzeichen. Und es unterstützt internationale TLDs.
Vitaly

285

URLs durch Links ersetzen (Antwort auf das allgemeine Problem)

Der reguläre Ausdruck in der Frage übersieht viele Randfälle. Beim Erkennen von URLs ist es immer besser, eine spezialisierte Bibliothek zu verwenden, die internationale Domainnamen, neue TLDs wie .museumKlammern und andere Satzzeichen innerhalb und am Ende der URL sowie viele andere Randfälle verarbeitet. Im Blog-Beitrag von Jeff Atwood The Problem With URLs finden Sie eine Erläuterung einiger anderer Probleme.

Die beste Zusammenfassung der URL-Matching-Bibliotheken finden Sie in Dan Dascalescus Antwort+100
(Stand Februar 2014).


"Lassen Sie einen regulären Ausdruck mehr als eine Übereinstimmung ersetzen" (Antwort auf das spezifische Problem)

Fügen Sie am Ende des regulären Ausdrucks ein "g" hinzu, um den globalen Abgleich zu ermöglichen:

/ig;

Dies behebt jedoch nur das Problem in der Frage, bei der der reguläre Ausdruck nur die erste Übereinstimmung ersetzte. Verwenden Sie diesen Code nicht.


150

Ich habe einige kleine Änderungen an Travis 'Code vorgenommen (nur um unnötige Neuerklärungen zu vermeiden - aber es funktioniert hervorragend für meine Bedürfnisse, also gute Arbeit!):

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
Wie kann man diesen Code bearbeiten, um eingebettete Objekte und Iframes nicht zu beschädigen? (Eingebettete Youtube-Objekte und Iframes)
Pradyut Bhattacharya

5
Es gibt einen Fehler im Code, der mit den E-Mail-Adressen hier übereinstimmt. [a-zA-Z]{2,6}sollte etwas in der Art von lesen, (?:[a-zA-Z]{2,6})+um kompliziertere Domain-Namen zu finden, dh email@example.co.uk.
Roshambo

1
Ich bin auf einige Probleme gestoßen; Zuerst wird nur http: // oder http: // www (ohne Leerzeichen www, sogar SO analysiert dies anscheinend falsch) einen Link erstellen. Und Links zu http: // www. Domain. com (ohne Leerzeichen) erstellt einen leeren Link und dann einen mit einem angehängten Ankerschließungs-Tag im Feld href.
Alfred

1
Was ist mit URLs ohne http://oder www? Funktioniert dies für diese Art von URLs?
Nathan

2
Ich habe versucht, den ursprünglichen Beitrag zu bearbeiten, um das Mailto-Problem zu beheben, aber ich muss mindestens 6 Zeichen hinzufügen, um eine Bearbeitung vorzunehmen. Aber wenn Sie diese Zeile ändern: replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;Damit ist replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;das Mailto-Problem
behoben

70

Travis ' Linkify()Code wurde oben optimiert . Ich habe auch einen Fehler behoben, bei dem E-Mail-Adressen mit Subdomain-Formaten nicht übereinstimmten (z. B. example@domain.co.uk).

Außerdem habe ich die Implementierung geändert, um die StringKlasse als Prototyp zu erstellen, sodass Elemente wie folgt abgeglichen werden können:

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

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

Wie auch immer, hier ist das Drehbuch:

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>');
    };
}

Das Beste meiner Meinung nach, da Prototyp-Funktionen die Dinge so viel sauberer machen :)
MRVDOG

es scheint, dass es mit solchen E-Mail-Adressen nicht funktioniert: info@some-thing.com some.thing@example.com etc ..
Marco Gagliardi

@ MarcoGagliardi Guter Fang. Fest.
Roshambo

1
Dies funktioniert nicht für die Zeichenfolge "git clone aaaa@bitbucket.org/ooo/bbb-cc-dd.git ". Es brach die Schnur in Stücke und erstellte mehrere Anker wie diesen "Git-Klon <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> "
Jebin

1
Es funktioniert nicht mit +E-Mail-Benutzernamen wie foo+bar@domain.com. Ich habe es mit einem E-Mail-Muster behoben /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim(beachten Sie das +in den ersten Klammern), aber ich weiß nicht, ob das etwas anderes kaputt macht.
Dchacke

24

Danke, das war sehr hilfreich. Ich wollte auch etwas, das Dinge verknüpft, die wie eine URL aussehen - als Grundvoraussetzung würde es etwas wie www.yahoo.com verknüpfen, selbst wenn das Protokollpräfix http: // nicht vorhanden wäre. Also im Grunde, wenn "www". vorhanden ist, wird es verlinken und davon ausgehen, dass es http: // ist. Ich wollte auch, dass aus E-Mails Mailto: Links werden. BEISPIEL: www.yahoo.com würde in www.yahoo.com konvertiert

Hier ist der Code, den ich erhalten habe (Kombination aus Code von dieser Seite und anderen Dingen, die ich online gefunden habe, und anderen Dingen, die ich selbst gemacht habe):

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
}

Beim zweiten Ersetzen ersetzt der Teil (^ | [^ /]) nur www.whatever.com, wenn ihm nicht bereits // - vorangestellt ist, um Doppelverknüpfungen zu vermeiden, wenn beim ersten Ersetzen bereits eine URL verknüpft wurde. Es ist auch möglich, dass sich www.whatever.com am Anfang der Zeichenfolge befindet. Dies ist die erste "oder" Bedingung in diesem Teil der Regex.

Dies könnte als jQuery-Plugin integriert werden, wie oben von Jesse P dargestellt - aber ich wollte speziell eine reguläre Funktion, die nicht auf ein vorhandenes DOM-Element einwirkt, da ich den vorhandenen Text nehme und ihn dann dem DOM hinzufüge Ich möchte, dass der Text "verknüpft" wird, bevor ich ihn hinzufüge, also übergebe ich den Text durch diese Funktion. Funktioniert super.


1
Es gibt ein Problem mit dem 2. Muster, das ganz einfach mit "www.domain.com" übereinstimmt. Das Problem besteht, wenn die URL eine Art Verweis enthält, z. B.: & 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 - In diesem Fall wird der Link automatisch erneut verknüpft. Eine schnelle Lösung besteht darin, das Zeichen "f" nach der negierten Liste mit "/" einzufügen. Der Ausdruck lautet also: replacePattern2 = /(^|[^\/f‹)(www\.[\S‹+(\b|$))/gim
Redtopia

Der obige Code wird viele Tests für Randfälle nicht bestehen. Wenn Sie URLs erkennen, ist es besser, sich auf eine spezielle Bibliothek zu verlassen. Hier ist warum .
Dan Dascalescu

2
Ich habe es gerade auf einer Zeichenfolge ausgeführt, auf der einige der Weblinks bereits einen href-Link enthalten. In diesem Fall können die vorhandenen Arbeitsverbindungen nicht durcheinander gebracht werden.
AdamJones

17

Das Identifizieren von URLs ist schwierig, da sie häufig von Satzzeichen umgeben sind und Benutzer häufig nicht die vollständige Form der URL verwenden. Es gibt viele JavaScript-Funktionen zum Ersetzen von URLs durch Hyperlinks, aber ich konnte keine finden, die genauso gut funktioniert wie der urlizeFilter im Python-basierten Webframework Django. Ich habe daher Djangos urlizeFunktion auf JavaScript portiert :

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

Ein Beispiel:

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;"

Wenn das zweite Argument wahr ist, wird rel="nofollow"es eingefügt. Das dritte Argument, falls zutreffend, entgeht Zeichen, die in HTML eine besondere Bedeutung haben. Siehe die README-Datei .


Funktioniert auch mit HTML-Quellen wie: www.web.com <a href = "https://github.com.com> url </ a> Text
Paulius Zaliaduonis

@Paulius: Wenn Sie die Option django_compatibleauf false setzen, wird dieser Anwendungsfall etwas besser behandelt.
Vebjorn Ljosa

Django's urlizeunterstützt TLDs nicht richtig (zumindest nicht den JS-Port auf GitHub). Eine Bibliothek, die TLDs ordnungsgemäß verarbeitet, ist JavaScript Linkify von Ben Alman .
Dan Dascalescu

Unterstützung für die Erkennung von URLs mit zusätzlichen Top-Level-Domains, auch wenn die URL nicht mit "http" oder "www" beginnt, wurde hinzugefügt.
Vebjorn Ljosa

10

Ich habe eine Änderung an Roshambo String.linkify () an emailAddressPattern vorgenommen, um aaa.bbb. @ Ccc.ddd-Adressen zu erkennen

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>');
    };
}

Der obige Code wird viele Tests für Randfälle nicht bestehen. Wenn Sie URLs erkennen, ist es besser, sich auf eine spezielle Bibliothek zu verlassen. Hier ist warum .
Dan Dascalescu

9

Ich habe auf Google nach etwas Neuerem gesucht und bin auf Folgendes gestoßen:

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

Demo: http://jsfiddle.net/kachibito/hEgvc/1/

Funktioniert sehr gut für normale Links.


Was ist hier "Normale Links"? Schauen Sie sich hier die Gabelung Ihrer Demo an: jsfiddle.net/hEgvc/27 Die Leute würden unbedeckt abdecken und dies auf einfache Weise machen. URI ist gemäß RFC3986 nicht einfach und wenn Sie nur "Normale Links" behandeln möchten, empfehle ich, mindestens diesen regulären Ausdruck zu befolgen: ^ (([^: /? #] +) :)? (// ([) ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
Ivan

2
Ich habe alles im Format http://example.com/folder/folder/folder/oder so gemeint https://example.org/blah- nur das typische nicht verrückte URL-Format, das 95-99% der Anwendungsfälle entspricht. Ich verwende dies für einen internen Verwaltungsbereich, daher brauche ich nichts Besonderes, um Edge-Cases oder Hash-Links abzufangen.
entartet


5

Diese Lösung funktioniert wie viele andere und verwendet tatsächlich denselben regulären Ausdruck wie einer von ihnen. Anstatt jedoch einen HTML-String zurückzugeben, wird ein Dokumentfragment zurückgegeben, das das A-Element und alle anwendbaren Textknoten enthält.

 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;
}

Es gibt einige Einschränkungen, insbesondere bei älterer IE- und textContent-Unterstützung.

Hier ist eine Demo.


2
@DanDascalescu Anstatt pauschal das Los abzustimmen, können Sie Ihre genannten Randfälle angeben.
Rlemon

Muss ich? Sehen Sie sich den Komponenten-Regexp für URLs an . Wenn Sie jedoch darauf bestehen, laufen Sie gegen die Linkify-Testsuite von Ben Alman . Ich habe angefangen , fehlgeschlagene Tests beizusteuern , z. B. für URL , aber bald wurde mir klar, dass es sich lohnt, dies nur für ernsthafte Bibliotheksanstrengungen zu tun. Bei allem Respekt handelt es sich bei der obigen Antwort um eine StackOverflow-Antwort, nicht um eine Open-Source-Bibliothek, die versucht, URLs korrekt zu analysieren.
Dan Dascalescu

2
Es gibt also Randfälle. wunderbar. Diese Antworten können für andere immer noch nützlich sein, und eine pauschale Herabstimmung scheint übertrieben. Die anderen Antworten, die Sie kommentiert und scheinbar abgelehnt haben, enthalten nützliche Informationen (sowie Ihre Antwort). Nicht jeder wird gegen diese Fälle vorgehen, und nicht jeder wird eine Bibliothek nutzen wollen.
Rlemon

Genau. Diejenigen, die die Einschränkungen von Regexps nicht verstehen, sind diejenigen, die gerne den ersten Regexp aus der am besten bewerteten Antwort überfliegen und damit arbeiten. Das sind die Leute, die am meisten Bibliotheken benutzen sollten.
Dan Dascalescu

1
Aber wie ist diese Rechtfertigung, jede Antwort mit nicht von Ihnen bevorzugten Lösungen abzustimmen?
Rlemon

4

Wenn Sie einen kürzeren Link (nur Domain), aber dieselbe lange URL anzeigen müssen, können Sie meine Änderung der oben angegebenen Codeversion von Sam Hasler ausprobieren

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>");
}

Unten sind einige getestete Zeichenfolgen aufgeführt:

  1. Finden Sie mich auf www.google.com
  2. www
  3. Finde mich auf www. http://www.com
  4. Folgen Sie mir auf: http://www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. Folgen Sie mir auf: http://www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

Hinweis: Wenn Sie nicht wwwals gültig übergeben möchten, verwenden Sie einfach unten reg ex: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig


Der obige Code wird viele Tests für Randfälle nicht bestehen. Wenn Sie URLs erkennen, ist es IMMER besser, sich auf eine spezielle Bibliothek zu verlassen. Hier ist warum .
Dan Dascalescu

3

Die Warnungen zur URI-Komplexität sollten beachtet werden. Die einfache Antwort auf Ihre Frage lautet jedoch:
Um jede Übereinstimmung zu ersetzen, müssen Sie das /gFlag am Ende des RegEx hinzufügen :
/(\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/>(");
}

einfaches Beispiel


2

Halte es einfach! Sagen Sie, was Sie nicht haben können, anstatt was Sie haben können :)

Wie oben erwähnt, können URLs sehr komplex sein, insbesondere nach dem "?", Und nicht alle beginnen mit einem "www". z.Bmaps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

Also, anstatt einen komplexen regulären Ausdruck zu haben, der nicht alle Randfälle erfüllt und schwer zu pflegen ist, wie wäre es mit diesem viel einfacheren, der für mich in der Praxis gut funktioniert.

Spiel

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

www. (anything but a space)+

Wo 'irgendetwas' ist [^'"<>\s] ... im Grunde genommen ein gieriges Match, bei dem Sie ein Leerzeichen, ein Zitat, eine spitze Klammer oder ein Zeilenende treffen

Ebenfalls:

Denken Sie daran, zu überprüfen, ob es nicht bereits im URL-Format vorliegt, z. B. enthält der Text href="..."odersrc="..."

Fügen Sie ref = nofollow hinzu (falls zutreffend)

Diese Lösung ist nicht so "gut" wie die oben genannten Bibliotheken, aber viel einfacher und funktioniert in der Praxis gut.

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

Die korrekte URL-Erkennung mit Unterstützung für internationale Domains und Astralzeichen ist keine triviale Sache. linkify-itDie Bibliothek erstellt Regex unter vielen Bedingungen und die endgültige Größe beträgt ca. 6 Kilobyte :). Es ist genauer als alle Bibliotheken, auf die derzeit in der akzeptierten Antwort verwiesen wird.

In der Linkify-It-Demo können Sie alle Edge-Fälle live überprüfen und Ihre testen.

Wenn Sie eine HTML-Quelle verknüpfen müssen, sollten Sie sie zuerst analysieren und jedes Text-Token separat durchlaufen.



0

Ich musste das Gegenteil tun und HTML-Links nur in die URL einfügen, aber ich habe Ihren regulären Ausdruck geändert und es funktioniert wie ein Zauber, danke :)

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

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

Ich verstehe den Sinn Ihrer Regex nicht. Es passt zu allem und ersetzt alles durch alles. Tatsächlich tut Ihr Code nichts.
Chad Grant

8
Ich denke, ich sollte warten, um einen Kommentar abzugeben, damit die Leute die Bearbeitung beenden können. Es tut uns leid.
Chad Grant

0

Die E-Mail-Erkennung in der obigen Antwort von Travitron hat bei mir nicht funktioniert, daher habe ich sie durch Folgendes erweitert / ersetzt (C # -Code).

// 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);

Dies ermöglicht E-Mail-Adressen wie " firstname.secondname@one.two.three.co.uk ".


Der obige Code wird viele Tests für Randfälle nicht bestehen. Wenn Sie URLs erkennen, ist es IMMER besser, sich auf eine spezielle Bibliothek zu verlassen. Hier ist warum .
Dan Dascalescu

Danke, @DanDascalescu Normalerweise ist es immer besser, zu stark zu verallgemeinern.
Uwe Keim

0

Nach Eingaben aus mehreren Quellen habe ich jetzt eine Lösung, die gut funktioniert. Es hatte damit zu tun, einen eigenen Ersatzcode zu schreiben.

Antwort .

Geige .

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
Der obige Code (und die meisten regulären Ausdrücke im Allgemeinen) werden viele Tests für Randfälle nicht bestehen. Wenn Sie URLs erkennen, ist es besser, sich auf eine spezielle Bibliothek zu verlassen. Hier ist warum .
Dan Dascalescu

Dan, gibt es so eine Bibliothek? In diesem Fall würden wir jedoch immer noch mit dem obigen regulären Ausdruck übereinstimmen, sodass der Code niemals Müll ausgeben kann, wenn etwas wie Müll verwendet wird (selbst wenn eine andere Bibliothek den Müll als gültige URL / URI zertifiziert).
Mike Mestnik


0

Hier ist meine Lösung:

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

Versuchen Sie die folgende Funktion:

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

Versuchen Sie es mit der folgenden Lösung

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.