Programming

일반 URL을 링크로 바꾸는 방법?

procodes 2020. 2. 18. 22:56
반응형

일반 URL을 링크로 바꾸는 방법?


주어진 텍스트 내에서 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>"); 
}

첫째, URL을 구문 분석하기 위해 자신의 정규 표현식을 굴리는 것은 끔찍한 아이디어 입니다. RFC 에 따르면 이것이 누군가가 라이브러리를 작성, 디버그 및 테스트 했을 때의 일반적인 문제라고 생각해야합니다 . URI는 복잡 - 아웃 확인 Node.js를에서 URL 파싱 코드 와의 위키 백과 페이지 URI 체계를 .

국제 도메인 이름 , 실제 ( .museum) vs 존재하지 않는 ( .etc) TLD, 괄호를 포함한 이상한 구두점 , URL 끝의 구두점, IPV6 호스트 이름 등 URL 을 구문 분석 할 때 매우 다양한 경우가 있습니다 .

내가 검토 한 라이브러리 , 일부 단점에도 불구하고 사용하는 몇 가지 가치가있다 :

이 작업을 위해 신속하게 실격 된 라이브러리 :

정규식을 고집하면 ComponentURL regexp 가 가장 포괄적 이지만, 존재하지 않는 2 글자 TLD를 살펴보면 잘못 감지 할 수 있습니다.


URL을 링크로 바꾸기 (일반적인 문제에 대한 답변)

질문의 정규식 은 많은 경우를 놓칩니다. URL을 감지 할 때는 항상 국제 도메인 이름,와 같은 새로운 TLD .museum, 괄호 및 URL 내부 및 끝에있는 구두점 및 기타 여러 가지 경우 를 처리하는 특수 라이브러리를 사용하는 것이 좋습니다 . 다른 문제에 대한 설명은 Jeff Atwood의 블로그 게시물 URL 관련 문제를 참조하십시오.

URL 매칭 라이브러리의 가장 요약댄 Dascalescu의 대답+100
(2014 2월 현재)


"정규식으로 두 개 이상의 일치 항목을 교체하십시오"(특정 문제에 대한 답변)

전역 표현식을 사용하려면 정규식 끝에 "g"를 추가하십시오.

/ig;

그러나 정규 표현식이 첫 번째 일치 항목 만 바꾸는 문제의 문제 만 수정합니다. 해당 코드를 사용하지 마십시오.


Travis의 코드를 약간 수정했습니다 (불필요한 재 선언을 피하기 위해-그러나 그것은 내 필요에 따라 잘 작동합니다!) :

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

Linkify()위에서 Travis의 코드 를 일부 최적화했습니다 . 또한 하위 도메인 유형 형식의 이메일 주소가 일치하지 않는 버그를 수정했습니다 (예 : 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>');
    };
}

감사합니다. 매우 도움이되었습니다. 또한 URL처럼 보이는 것들을 연결하는 무언가를 원했습니다. 기본 요구 사항은 http : // 프로토콜 접두사가없는 경우에도 www.yahoo.com과 같은 것을 연결하는 것입니다. 기본적으로 "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
}

두 번째 교체에서 (^ | [^ /]) 부분은 //가 접두사로 붙지 않은 경우 www.whatever.com 만 //로 대체합니다. URL이 첫 번째 교체에서 이미 링크 된 경우 이중 연결을 피하기위한 것입니다. 또한 www.whatever.com이 문자열의 시작 부분에있을 수 있습니다. 이는 정규 표현식의 해당 부분에서 첫 번째 "조건"입니다.

Jesse P가 위에서 설명한 것처럼 jQuery 플러그인으로 통합 될 수는 있지만 기존 DOM 요소에 대해 작동하지 않는 일반 함수를 원했습니다. 텍스트를 가져 와서 DOM에 추가하기 때문입니다. 텍스트를 추가하기 전에 "연결"되기를 원하므로이 함수를 통해 텍스트를 전달합니다. 잘 작동합니다.


URL은 구두점으로 둘러싸여 있고 사용자가 URL의 전체 형식을 자주 사용하지 않기 때문에 URL을 식별하기가 까다 롭습니다. URL을 하이퍼 링크로 대체하기위한 많은 JavaScript 함수가 존재하지만 urlizePython 기반 웹 프레임 워크 Django에서 필터 뿐만 아니라 작동하는 함수도 찾을 수 없습니다 . 따라서 Django의 urlize기능을 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;"

두 번째 인수가 true이면 rel="nofollow"삽입됩니다. 세 번째 인수 (true 인 경우)는 HTML에서 특별한 의미가있는 문자를 이스케이프합니다. README 파일을 참조하십시오 .


aaa.bbb. @ ccc.ddd 주소를 인식하기 위해 Roshambo String.linkify ()를 emailAddressPattern으로 변경했습니다.

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

나는 구글에서 새로운 것을 찾아서 이것을 가로 질러 달렸다.

$('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/

일반 링크에 정말 효과적입니다.


가장 좋은 스크립트 : http://benalman.com/projects/javascript-linkify-process-lin/


이 솔루션은 다른 많은 솔루션과 동일하게 작동하며 실제로는 그 중 하나와 동일한 정규식을 사용하지만 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 지원과 같은 몇 가지주의 사항이 있습니다.

여기 데모가 있습니다.


더 짧은 링크 (도메인 만 해당)를 표시해야하지만 동일한 긴 URL을 사용하려면 위에 게시 된 Sam Hasler의 코드 버전을 수정 해보십시오

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

정규직 : /(\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


URI의 복잡성에 대한 경고에 주목해야하지만 질문에 대한 간단한 대답은 다음과 같습니다.
모든 일치 항목을 바꾸려면 /gRegEx 끝에 플래그를 추가해야합니다 .
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi


간단하게 유지하십시오! 가질 수있는 것보다는 가질 수없는 것을 말하십시오. :)

위에서 언급했듯이 URL은 특히 '?'뒤에 매우 복잡 할 수 있으며 모든 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;

국제 도메인 및 아스트랄 문자 지원을 통한 올바른 URL 탐지는 사소한 것이 아닙니다. linkify-it라이브러리는 많은 조건 에서 정규식을 빌드 하며 최종 크기는 약 6 킬로바이트입니다. 현재 허용되는 답변에서 참조되는 모든 라이브러리보다 정확합니다.

linkify-it 데모참조 하여 모든 최신 사례를 확인하고 테스트하십시오.

HTML 소스를 연결해야하는 경우 먼저 HTML 소스를 구문 분석하고 각 텍스트 토큰을 개별적으로 반복해야합니다.


나는 또 다른 JavaScript 라이브러리를 작성했습니다. 가장 작은 크기의 오 탐지로 매우 민감하기 때문에 더 좋을 것입니다. 현재 적극적으로 유지 관리하고 있으므로 데모 페이지에서 테스트하여 어떻게 작동하는지 확인하십시오.

링크 : https://github.com/alexcorvi/anchorme.js


나는 반대로해야하고 URL에 HTML 링크를 만들어야했지만 정규 표현식을 수정하면 매력처럼 작동합니다. :)

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

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

위의 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 " 와 같은 이메일 주소를 허용합니다 .


여러 소스에서 입력 한 후 이제는 잘 작동하는 솔루션을 찾았습니다. 자체 교체 코드를 작성하는 것과 관련이 있습니다.

대답 .

바이올린 .

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

텍스트의 URL을 HTML 링크로 바꾸고 href / pre 태그 내의 URL을 무시하십시오. https://github.com/JimLiu/auto-link


내 해결책은 다음과 같습니다.

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

아래 기능을 사용해보십시오 :

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


아래 솔루션을 사용해보십시오

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

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

간단한 예

참고 URL : https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links

반응형