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


453

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

답변:


350

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

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

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

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

정규식을 고집하면 Component 의 URL 정규 표현식 이 가장 포괄적 이지만, 존재하지 않는 2 문자 TLD를 살펴보면 잘못 감지합니다.


3
그것은 URL regexp from Component언급되지 않은 것이 유감 이며, 그것이하고있는 일에 대한 설명이 도움이 될 것입니다. Autolinker.js매우 잘 주석을 달았으며 테스트를 거쳤습니다. Vebjorn Ljosa의 답변urlize.js 에 링크 된 라이브러리 는 테스트가 없지만 기능적이고 잘 유지됩니다.
— Sam Hasler

1
Regex101.com은 자동으로 정규 표현식을 "설명" 하지만 행운을 빕니다 :) 잘못된 TLD (동일한 링크)로 실패 사례를 빨리 발견했습니다.
— Dan Dascalescu

1
@ SamHasler : 자동 링커는 TLD 및 IDN 영역에서 개선해야합니다. 몇 가지 테스트를 추가했습니다 .
— Dan Dascalescu

2
URL 정규식 패턴 을 유지하려는 John Gruber의 노력에 대해 언급 한 사람이 아무도 없습니다 . 문제에 대한 유일한 / 이상적인 해결책은 아니지만, 자신의 솔루션을 롤링하는 경우 조사 할 가치가 있습니다. 이것을 참조로 추가하고 싶었습니다.
— oelna

2
@DanDascalescu이 markdown-it.github.io/linkify-it를 살펴보십시오 . 이 라이브러리는 텍스트에서 링크 패턴을 감지하여 정확히 하나의 작업에 중점을 둡니다. 그러나 나는 그것을 잘한다. 예를 들어, 아스트랄 문자를 포함하여 올바른 유니 코드 지원이 있습니다. 그리고 국제 TLD를 지원합니다.
— Vitaly

285

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

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

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


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

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

/ig;

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


150

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

1
포함 된 객체 및 iframe을 손상시키지 않도록이 코드를 편집하는 방법 .. (youtube 포함 된 객체 및 iframe)
— Pradyut Bhattacharya

5
코드에 이메일 주소와 일치하는 버그가 있습니다. 보다 복잡한 도메인 이름 (예 : email@example.co.uk)을 일치 [a-zA-Z]{2,6}시키려면 행을 따라 (?:[a-zA-Z]{2,6})+내용을 읽어야합니다.
— Roshambo

1
나는 몇 가지 문제에 부딪쳤다; 먼저 http : // 또는 http : // www 만 있으면 공간 이 없어도 www가 공백으로 잘못 구문 분석하여 링크를 만듭니다. 그리고 http : // www와 링크합니다. 도메인 . 공백없이 com은 하나의 빈 링크를 만들고 href 필드에 앵커 닫기 태그가 첨부 된 하나를 만듭니다.
— Alfred

1
http://또는 없는 URL은 www어떻습니까? 이런 종류의 URL에서 작동합니까?
— Nathan

2
mailto 문제를 해결하기 위해 원본 게시물을 편집하려고했지만 편집하려면 6 자 이상을 추가해야합니다. 그러나이 줄을 변경하면 : mailto 문제를 해결하는 replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;이것으로 replacePattern3 = /(\w+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;:)
— yourdeveloperfriend

70

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

내 의견으로는 최고, 프로토 타입 기능이 훨씬 더 깨끗해집니다 :)
— MRVDOG

info@some-thing.com some.thing@example.com 등 : 이메일 주소와 함께 작동하지 않는 것 같습니다
— 마르코 Gagliardi은

@MarcoGagliardi 잘 잡았습니다. 결정된.
— Roshambo

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> "
— Jebin

1
+와 같은 이메일 사용자 이름에서는 작동하지 않습니다 foo+bar@domain.com. 이메일 패턴 /[\w.+]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim( +첫 번째 괄호 안의 참고)으로 고정 했지만 다른 것이 깨지는지는 모르겠습니다.
— dchacke

24

감사합니다. 매우 도움이되었습니다. 또한 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에 추가하기 때문입니다. 텍스트를 추가하기 전에 "연결"되기를 원하므로이 함수를 통해 텍스트를 전달합니다. 잘 작동합니다.


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을 감지 할 때는 특수 라이브러리를 사용하는 것이 좋습니다. 이유는 다음과 같습니다 .
— Dan Dascalescu

2
방금 웹 링크 중 일부에 이미 href 링크가있는 문자열에서 실행했습니다. 이 경우 기존 작업 링크를 엉망으로 만드는 데 실패합니다.
— AdamJones

17

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 파일을 참조하십시오 .


또한 다음과 같은 html 소스와 함께 작동합니다 : www.web.com <a href = "https : // github
— .com">

@Paulius : 옵션 django_compatible을 false로 설정하면 해당 사용 사례를 조금 더 잘 처리합니다.
— Vebjorn Ljosa

Django urlize는 TLD를 올바르게 지원하지 않습니다 (적어도 GitHub의 JS 포트는 아닙니다). TLD를 올바르게 처리 하는 라이브러리 는 Ben Alman의 JavaScript Linkify 입니다.
— Dan Dascalescu

URL이 "http"또는 "www"로 시작하지 않는 경우에도 최상위 도메인이 추가 된 URL 감지를 지원합니다.
— Vebjorn Ljosa 2014

10

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

위의 코드는 엣지 케이스에 대한 많은 테스트에 실패합니다. URL을 감지 할 때는 특수 라이브러리를 사용하는 것이 좋습니다. 이유는 다음과 같습니다 .
— Dan Dascalescu

9

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

$('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에 따라 쉬운 일이 아니며 "일반 링크"만 다루려면 최소한 다음 정규 표현식을 따르는 것이 좋습니다. ^ (([^ : /? #] +) :)? (// ([ ^ /? #] *))? ([^? #] *) (\? ([^ #] *))? (# (. *))?
— Ivan

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 의 컴포넌트 정규 표현식을 살펴보십시오 . 그러나 당신이 주장한다면 Ben Alman의 linkify test suite 에 대해 달리십시오 . 나는 urlize 와 같은 실패한 테스트에 기여하기 시작 했지만 곧 심각한 라이브러리 노력에만 가치가 있음을 깨달았습니다. 모든 점에서 위의 내용은 URL을 올바르게 구문 분석하려는 오픈 소스 라이브러리가 아닌 StackOverflow 답변입니다.
— Dan Dascalescu

2
가장자리가 있습니다. 훌륭한. 이 답변은 여전히 ​​다른 사람들에게 유용 할 수 있으며 그들을 공감하는 담요는 과도한 것처럼 보입니다. 댓글을 달고 겉으로 드러난 것처럼 보이는 답변 에는 유용한 정보 (답변) 가 포함되어 있습니다. 모든 사람이 해당 사례에 반대되는 것은 아니며 모든 사람이 도서관을 사용하기를 원하는 것은 아닙니다.
— rlemon

바로 그거죠. 정규 표현식의 한계를 이해하지 못하는 사람들은 가장 많이 대답 한 답변에서 첫 번째 정규 표현식을 행복하게 훑어가는 사람들입니다. 도서관을 가장 많이 사용해야하는 사람들입니다.
— Dan Dascalescu

1
그러나 귀하가 선호하지 않는 솔루션 정규식으로 모든 답변을 다운 투표하는 것이 정당화되는 방법은 무엇입니까?
— rlemon

4

더 짧은 링크 (도메인 만 해당)를 표시해야하지만 동일한 긴 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>");
}

3

정규직 : /(\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을 감지 할 때는 항상 특수 라이브러리에 의존하는 것이 좋습니다. 이유는 다음과 같습니다 .
— Dan Dascalescu

3

URI의 복잡성에 대한 경고에 주목해야하지만 질문에 대한 간단한 대답은 다음과 같습니다.
모든 일치 항목을 바꾸려면 /gRegEx 끝에 플래그를 추가해야합니다 .
/(\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은 특히 '?'뒤에 매우 복잡 할 수 있으며 모든 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 킬로바이트입니다. 현재 허용되는 답변에서 참조되는 모든 라이브러리보다 정확합니다.

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

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



0

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

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

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을 감지 할 때는 항상 특수 라이브러리에 의존하는 것이 좋습니다. 이유는 다음과 같습니다 .
— Dan Dascalescu 5

감사합니다, @DanDascalescu 일반적으로, 과도하게 일반화하는 것이 좋습니다.
— Uwe Keim

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을 감지 할 때는 특수 라이브러리를 사용하는 것이 좋습니다. 이유는 다음과 같습니다 .
— Dan Dascalescu

댄, 그런 도서관 있어요? 이 경우 우리는 여전히 위의 정규 표현식과 일치하여 다른 라이브러리가 가비지를 유효한 URL / URI로 인증하더라도) 가비지가 출력되지 않도록 코드가 절대 가비지를 출력하지 않도록합니다.
— Mike Mestnik


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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.