478

以下の関数を使用して、特定のテキスト内の 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>"); 
}
4

25 に答える 25

286

URL をリンクに置き換える (一般的な問題への回答)

質問の正規表現は、多くのエッジ ケースを見逃しています。.museumURL を検出するときは、国際ドメイン名、 URL 内および URL の末尾にある括弧やその他の句読点などの国際ドメイン名、新しい TLD、およびその他の多くのエッジ ケースを処理する特殊なライブラリを使用することを常にお勧めします。その他の問題については、Jeff Atwood のブログ投稿The Problem With URLsを参照してください。

URL マッチング ライブラリの最適な要約は、Dan Dascalescu の Answer+100
(2014 年 2 月現在) にあります。


「複数の一致を正規表現で置換する」(具体的な問題への回答)

正規表現の末尾に「g」を追加して、グローバル マッチングを有効にします。

/ig;

しかし、それは、正規表現が最初の一致のみを置き換えていたという問題の問題を解決するだけです。そのコードは使用しないでください。

于 2008-09-01T10:00:52.217 に答える
168

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;
}
于 2010-10-08T11:50:19.133 に答える
75

上記の Travis の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>');
    };
}
于 2011-08-19T15:03:50.953 に答える
27

ありがとう、これはとても役に立ちました。また、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
}

2 番目の置換では、(^|[^/]) の部分は、最初の置換で URL が既にリンクされている場合に二重リンクを回避するために、// のプレフィックスが付いていない場合にのみ www.whatever.com を置換します。また、www.whatever.com が文字列の先頭にある可能性もあります。これは、正規表現のその部分の最初の「または」条件です。

これは、上記の Jesse P が示したように jQuery プラグインとして統合できますが、既存の DOM 要素に作用しない通常の関数が特に必要でした。追加する前にテキストを「リンク化」したいので、テキストをこの関数に渡します。よく働く。

于 2010-01-29T23:55:58.303 に答える
18

URL は句読点で囲まれていることが多く、ユーザーが完全な形式の URL を使用しないことが多いため、URL を識別するのは困難です。urlizeURL をハイパーリンクに置き換えるための JavaScript 関数は多数存在しますが、Python ベースの Web フレームワーク 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;"

2 番目の引数が true の場合、rel="nofollow"挿入されます。3 番目の引数が true の場合、HTML で特別な意味を持つ文字をエスケープします。README ファイルを参照してください。

于 2012-05-08T12:02:45.030 に答える
11

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>');
    };
}
于 2011-08-21T14:15:09.243 に答える
7

これを行うための最良のスクリプト:http: //benalman.com/projects/javascript-linkify-process-lin/

于 2010-06-25T05:18:20.043 に答える
6

このソリューションは他の多くのソリューションと同様に機能し、実際にはそれらの 1 つと同じ正規表現を使用しますが、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 のサポートなど、いくつかの注意点があります。

ここにデモがあります。

于 2012-11-22T19:03:47.937 に答える
5

短いリンク(ドメインのみ)を表示する必要があるが、同じ長いURLを使用している場合は、上記のSamHaslerのコードバージョンの変更を試すことができます。

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>");
}
于 2011-12-09T08:42:34.340 に答える
4

正規表現: /(\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注:有効なものとして 渡したくない場合は、以下の正規表現を使用してください:/(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig

于 2014-01-30T11:58:34.870 に答える
4

URI の複雑さに関する警告に注意する必要がありますが、質問に対する簡単な答えは次のとおりです。すべての一致を置き換えるには、RegEx の末尾にフラグを
追加する必要があります。/g
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi

于 2016-05-02T18:11:20.303 に答える
3

複雑にしないでおく!あなたが持つことができるものではなく、あなたが持つことができないものを言ってください:)

前述のように、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;
于 2014-05-27T10:58:46.040 に答える
3

国際ドメインとアストラル文字のサポートによる正確な URL 検出は、簡単なことではありません。linkify-itライブラリは多くの条件から正規表現を構築し、最終的なサイズは約 6 キロバイトです:)。現在受け入れられている回答で参照されているすべてのライブラリよりも正確です。

linkify-it デモを参照して、ライブのすべてのエッジ ケースをチェックし、自分のエッジ ケースをテストしてください。

HTML ソースをリンクする必要がある場合は、最初にそれを解析し、各テキスト トークンを個別に繰り返す必要があります。

于 2015-05-16T19:50:18.747 に答える
2

私はさらに別の JavaScript ライブラリを作成しました。これは非常に機密性が高く、誤検出が最小限に抑えられ、高速でサイズが小さいため、あなたにとってより良いものになるかもしれません。私は現在積極的にそれを維持しているので、デモ ページでテストして、どのように機能するかを確認してください。

リンク: https://github.com/alexcorvi/anchorme.js

于 2016-03-02T21:26:00.123 に答える
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 」のような電子メールアドレスが可能になります。

于 2010-02-12T08:02:16.520 に答える
1

私は反対のことをしなければならず、HTML リンクを URL だけにしましたが、正規表現を変更したところ、魅力的に機能しました。ありがとう :)

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

source = source.replace(exp,"$1");
于 2009-04-27T03:20:35.763 に答える
1

いくつかのソースからの入力の後、うまく機能するソリューションができました。独自の置換コードを作成する必要がありました。

答えてください。

フィドル

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;
    });
}
于 2013-11-04T16:59:21.930 に答える
0

テキスト内の URL を HTML リンクに置き換え、href/pre タグ内の URL を無視します。 https://github.com/JimLiu/auto-link

于 2015-06-11T21:31:44.743 に答える