2009-06-11 11 views
3

正規表現を使用して、テキストのURLをハイパーリンクに変換しようとしています。正規表現を使用してテキスト内の既存のリンクを邪魔することなく、URLをリンクに変換する正規表現

bla bla blah <a href="http://www.google.com">www.google.com</a> bla blah <a href="www.google.com">www.google.com</a> 

ない

bla bla blah <a href="http://www.google.com">www.google.com</a> bla blah <a href="<a href="http://www.google.com">www.google.com</a></a>"><a href="http://www.google.com">www.google.com</a></a> 
+0

は、あなたも*この問題のためにグーグル*試みたことがありますか?これは何度もここを通ってきていて、もう面白くなくなってしまいました(申し訳ありませんが、それは単なる事実です)。次をご覧ください:http://www.google.com/search?q=url+links+regex+replace+site%3Astackoverflow.com – Tomalak

+1

Tomalak、質問をお読みください。この問題は、Google検索で見つけたものよりも複雑です – amarillion

+1

@amarillion:問題のビットと部分については、ここでは説明しません。この正確な質問さえもここにありました。そして、「正規表現でHTMLをやってはいけません」、「コーナーケースではテキスト中のURLを一致させるのは難しく、不可能です。この質問は間違いなくそれにも傷つくことはありません。 – Tomalak

答えて

3

は、最後にそれを終え:

function add_url_links($data) 
{ 
     $data = preg_replace_callback('/(<a href=.+?<\/a>)/','guard_url',$data); 

     $data = preg_replace_callback('/(http:\/\/.+?)([ \\n\\r])/','link_url',$data); 
     $data = preg_replace_callback('/^(http:\/\/.+?)/','link_url',$data); 
     $data = preg_replace_callback('/(http:\/\/.+?)$/','link_url',$data); 

     $data = preg_replace_callback('/{{([a-zA-Z0-9+=]+?)}}/','unguard_url',$data); 

     return $data; 
} 

function guard_url($arr) { return '{{'.base64_encode($arr[1]).'}}'; } 
function unguard_url($arr) { return base64_decode($arr[1]); } 
function link_url($arr) { return guard_url(array('','<a href="'.$arr[1].'">'.$arr[1].'</a>')).$arr[2]; } 
+0

あなたのソリューションは革新的ですが、あなたの正規表現の言語が見えない場合は、単純に'(?<!href = ")'をあなたの変換式。 – Nicole

3

これを生じるはずであるので、

bla bla blah www.google.com bla blah <a href="www.google.com">www.google.com</a> 

を私はこれを達成するために管理しているが、既存のリンクがテキスト

に既に存在しているときに問題があります1つの正規表現ではほとんど不可能です。私は、代わりにステートマシンベースのアプローチをお勧めします。 (擬似コードで)このような何か

state = OUTSIDE_LINK 
for pos (0 .. length input) 
    switch state 
    case OUTSIDE_LINK 
    if substring at pos matches /<a/ 
     state = INSIDE_LINK 
    else if substring at pos matches /(www.\S+|\S+.com|\S+.org)/ 
     substitute link 
    case INSIDE_LINK 
    if substring at post matches /<\/a>/ 
     state = OUTSIDE_LINK 
+1

@Tomalak - 謝罪、私は前に同様の質問を検索するために最善を尽くしました - 同様の記事を見つけましたが、私の質問に答えた人はいません @amarillionありがとうございます。私は否定的なルックバックを使用してそれを行う方法がなければならないと確信していますか?しかし、この答えは、私がやろうとしていることには完璧です。 – Ben

2

(PHPで)それを行うための別の方法は

$strParts = preg_split('/(<[^>]+>)/', $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 
    foreach($strParts as $key=>$part) { 

     /*check this part isn't a tag or inside a link*/ 
     if(!(preg_match('@(<[^>]+>)@', $part) || preg_match('@(<a[^>]+>)@', $strParts[$key - 1]))) { 
      $strParts[$key] = preg_replace('@((http(s)?://)?(\S+\.{1}[^\s\,\.\!]+))@', '<a href="http$3://$4">$1</a>', $strParts[$key]); 
     } 

    } 
    $html = implode($strParts); 
+0

コードに「未定義オフセット:-1」というエラーがあります。 'preg_match( '@()+>)@、$ strParts [$ key-1])'を 'preg_match(' @()+>)@に変更することです。 ' –

1

もう一つのトリックは、その後、コードをコードでURLを置き換えることにより、すべての既存のリンクを守るためにありますリンクを作成し、保護されたリンクのエンコードを解除します。

$data = 'test http://foo <a href="http://link">LINK</a> test'; 

$data = preg_replace_callback('/(<a href=".+?<\/a>)/','guard_url',$data); 

$data = preg_replace_callback('/(http:\/\/.+?)([ .\\n\\r])/','link_url',$data); 

$data = preg_replace_callback('/{{([a-zA-Z0-9+]+?)}}/','unguard_url',$data); 

print $data; 

function guard_url($arr) { return '{{'.base64_encode($arr[1]).'}}'; } 
function unguard_url($arr) { return base64_decode($arr[1]); } 
function link_url($arr) { return '<a href="'.$arr[1].'">'.$arr[1].'</a>'.$arr[2]; } 

上記のコードは概念の証明であり、すべての状況を処理するものではありません。それでも、コードはかなり簡単です。

関連する問題