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>"); 
}
Sergio del Amo
quelle

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.

Dan Dascalescu
quelle
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.

Sam Hasler
quelle
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;
}
cloud8421
quelle
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 protected].
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. [email protected]).

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 = '[email protected]';
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>');
    };
}
Roshambo
quelle
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: [email protected] [email protected] etc ..
Marco Gagliardi
@ MarcoGagliardi Guter Fang. Fest.
Roshambo
1
Dies funktioniert nicht für die Zeichenfolge "git clone [email protected]/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:[email protected]"> [email protected] </a> / ooo / bbb-cc-dd.git "> https: // <a href="mailto:[email protected]"> [email protected] </a> /ooo/bbb-cc-dd.git </a> "
Jebin
1
Es funktioniert nicht mit +E-Mail-Benutzernamen wie [email protected]. 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.

Travis
quelle
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 .

Vebjorn Ljosa
quelle
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>');
    };
}
Christian Koch
quelle
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.

degenerieren
quelle
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.

rlemon
quelle
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>");
}
Artjom Kurapov
quelle
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

Nishant Kumar
quelle
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

Moritz
quelle
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

Zuhair Taha
quelle
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;
Andrew Murphy
quelle
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.

Vitaly
quelle
1

Ich habe noch eine weitere JavaScript-Bibliothek geschrieben, die möglicherweise besser für Sie ist, da sie sehr empfindlich ist und die geringstmöglichen Fehlalarme aufweist, schnell und klein ist. Ich pflege es derzeit aktiv. Bitte testen Sie es auf der Demoseite und sehen Sie, wie es für Sie funktionieren würde.

Link: https://github.com/alexcorvi/anchorme.js

Alex C.
quelle
Tolle Bibliothek. Vielen Dank!
Serdar Değirmenci
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");

quelle
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 " [email protected] ".

Uwe Keim
quelle
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;
    });
}
Mike Mestnik
quelle
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;
    }
}
AndroidDev
quelle
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/"));

Moonis Abidi
quelle
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;
}
Rahul Hirve
quelle