2009-06-11 10 views
3

Ich versuche, URLs in einem Text in Hyperlinks zu konvertieren - mit regulären Ausdrücken. Ich habe es geschafft, dies zu erreichen, aber das Problem ist, wenn es bereits vorhandene Links im Textregex, um URLs in Links zu verwandeln, ohne mit vorhandenen Links im Text zu verkehren

so

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

in

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

nicht

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

Haben Sie selbst * versucht * für dieses Problem googeln? Das ist hier schon so oft passiert, dass es gar nicht mehr witzig ist (tut mir leid, wenn das abweisend klingt, es ist nur eine Tatsache). Sehen Sie sich an: http://www.google.com/search?q=url+links+regex+replace+site%3Astackoverflow.com – Tomalak

+1

Tomalak, lesen Sie die Frage. Dieses Problem ist komplizierter als das, was Sie mit dieser Google-Suche finden – amarillion

+1

@amarillion: Bits und Teile des Problems wurden hier bis zu keinem Ende diskutiert. Sogar diese genaue Frage ist hier gewesen. Und jedes Mal, wenn es auf "HTML nicht mit Regex" brennt, und "übereinstimmende URLs in einem Text ist hart und unmöglich in den Fällen". Diese Frage wird zweifellos auch darauf niederbrennen. – Tomalak

Antwort

3

Schließlich beendete er:

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

Ihre Lösung ist innovativ, aber ich denke, dass es viel einfacher und schneller sein könnte, wenn Ihre Regex-Sprache Look-Behinds hat - fügen Sie einfach' (? Nicole

3

Dieses Ergebnis sollte ist fast unmöglich mit einem einzigen regulären Ausdruck zu tun. Ich würde stattdessen einen State-Machine-basierten Ansatz empfehlen. So etwas wie dies (in Pseudo-Code)

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 - Entschuldigung, ich habe mein Bestes versucht, ähnliche Fragen vorher zu suchen - und ähnliche Beiträge gefunden, aber keine, die meine Frage beantwortet haben @amarillion Vielen Dank, das funktioniert. Ich bin mir sicher, dass es einen Weg geben muss, negative Rückblicke zu machen. Aber diese Antwort ist perfekt für das, was ich versucht habe. – Ben

2

Ein anderer Weg, es zu tun (in 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

Ihr Code hat einen Fehler 'Undefined offset: -1'. Das Problem ist, 'preg_match ('@ () +>) @', $ strParts [$ key - 1])' '' 'preg_match ('@ () +>) @', $ strParts [$ key? $ key - 1: 0]) ' –

1

Ein weiterer Trick ist es, alle bestehenden Verbindungen zu schützen, indem Sie den Code kodiert, dann ersetzt Urls mit Links und entschlüsseln dann die geschützten Links.

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

Der obige Code ist nur ein Beweis des Konzepts und behandelt nicht alle Situationen. Dennoch können Sie sehen, dass der Code ziemlich einfach ist.

Verwandte Themen