2012-03-29 16 views
0

配列に格納されているテキストの特定のキーワードをリンクに変換しようとしています。自動的にキーワードをPHPのリンクに変換する

例のテキスト:

$text='This text contains many keywords, but also formated <a href="#keywords" title="keywords">keywords</a>.' 

は、だから今は、キーワード<a href="#keywords" title="keywords">#keywords</a>に単語を変換したいです。

私は

preg_replace('/keywords/i',' <a href="#keywords">keywords</a> ',$text); 

非常にシンプルにpreg_replace関数を使用しますが、明らかに、それはまた、すでにリンクとしてフォーマットされた文字列をリンクに変換したので、私のような厄介なHTMLを取得:

$text='This text contains many <a href="#keywords" title="keywords">keywords</a>, but also formated <a href="#<a href="#keywords" title="keywords">keywords</a>" title="<a href="#keywords" title="keywords">keywords</a>"><a href="#keywords" title="keywords">keywords</a></a>.' 

を期待される結果:

$text='This text contains many <a href="#keywords" title="keywords">keywords</a>, but also formated <a href="#keywords" title="keywords">keywords</a>.' 

何か提案がありますか? THX

EDIT

は、我々は完璧な機能から一歩ですが、それでもこのような場合にはうまく機能していません。この場合

$text='This text contains many keywords, but also formated 
     <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.' 

それがHREFでも、単語keywordsを置き換えます私たちは再び乱雑なコードを手に入れます。

<a href="http://www.<a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.com/<a href="http://www.keywords.com/keywords" title="keywords">keywords</a>" title="keywords">keywords</a> 
+0

が、「#something」のhrefが実際に有効な参照されるので、私は、例えば、パーセント記号を何か他のものを使用することをお勧め:

は、ここで私はそれをやった方法ですあなたがいつか普通のリンクを偶然に置き換えることはないということです。 – deed02392

+0

実際には、単語を表示するための単なる例であり、キーワードはhref = ""でも発生する可能性があります。 – jakubos

+0

それはちょうど私のポイントを補強する。あなたは私が言ったことをもう一度読まなければならない。 :) – deed02392

答えて

2

私は普通ではありません式には、多分、この1は動作します:私はそれを行うだろうと思い何

/[^#>"]keywords/i 

#keywords>keywords、および"keywordsのすべてのインスタンスを無視し、残りを見つけることです。


EDIT

それをテストした後、それはそれは同様に単語の前にスペースを置き換えるように見える、とkeywordsは、文字列の先頭にある場合は動作しません。また、元の資本金は保存されませんでした。私はこの1つをテストしている、そしてそれは私のために完璧に動作します:

$string = "Keywords and keywords, plus some more keywords with the original <a href=\"#keywords\" title=\"keywords\">keywords</a>."; 
$string = preg_replace("/(?<![#>\"])keywords/i", "<a href=\"#keywords\">$0</a>", $string); 
echo $string; 

最初の3が交換され、オリジナルの総額を維持し、そして最後の一つがそのまま残されています。これはnegative lookbehindbackreferencesを使用します。


EDIT 2:

OP編集した質問です。提供された新しい例では、次の正規表現は動作します:これは#>".、または/が先行されていないkeywordsのすべてのインスタンスを置き換えます

$string = 'This text contains many keywords, but also formated <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.'; 
$string = preg_replace("/(?<![#>\".\/])keywords/i", "<a href=\"http://www.keywords.com/keywords\" title=\"keywords\">$0</a>", $string); 
echo $string; 

// outputs: This text contains many <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>, but also formated <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>. 

+0

は動作しますが、あなたはhttp://www.regextester.com/で確認できます。 – JKirchartz

+0

@JKirchartz:ありがとう、そのサイトについては知りませんでした。それを試した後、私は私の答えでいくつかの欠陥を見つけました...更新された答えを見てください。 – Travesty3

+0

ありがとう、これは素晴らしいですが、まだ1つのバグがあります。私の質問で**編集**をご覧ください。 thx – jakubos

0

RegExを変更して、スペースのあるキーワードをターゲットにすることができます。フォーマットされたキーワードには空白が含まれないためです。ここに例があります。ここで

$text = preg_replace('/ keywords/i',' <a href="#keywords">keywords</a>',$text); 
+0

はい、私は試しましたが、 2つのリンクを一緒に混ぜる。どうも – jakubos

1

は問題です:

キーワードがsanityだったとあなたはすでにhref="insanity"を持っていた場合は、キーワードのような(HREF、タイトル、またはリンクのテキスト内の、どこそこに可能性。それは前後にスペースを持っている(それは他のすべての可能な基準に適合していても、上記の例では

<a href="http://example.org/">Click here to find more keywords and such!</a> 

:またはさらに悪いことに、あなたのような非キーワードキーワードを含むように起こるのリンク、何かを持っている可能性があり最も簡単なこと1つはテストする)、それはまだ私はインターネットを壊すと思うリンク内のリンクになります。

このため、キーワードがリンクでラップされているかどうかを確認するには、lookaheadslookbehindsを使用する必要があります。しかし、一つのキャッチがあります:lookbehindsは定義されたパターン(ワイルドカードを意味しない)を持たなければなりません。

私はの効果にものになるだろうこれは、ヒーローになると、あなたの問題のために簡単な修正を表示しようと思いました:あなたがこの中にあるため後読みことを行うことができない場合を除き

'/(?<!\<a.?>)[list|of|keywords](?!\<\/a>)/' 

ケースにそのワイルドカードがあります。それがなければ、あなたは非常に貪欲な表現に終わります。

代わりに、すべてのリンク要素を見つけるためにregexを使用し、プレースホルダでスワップして最後にプレースホルダに置き換えることをstr_replaceとします。ちょうど私の2セント

$text='This text contains many keywords, but also formated <a href="#keywords" title="keywords">keywords</a>.'; 
$keywords = array('text', 'formatted', 'keywords'); 

//This is just to make the regex easier 
$keyword_list_pattern = '['. implode($keywords,"|") .']'; 

// First, get all matching keywords that are inside link elements 
preg_match_all('/<a.*' . $keyword_list_pattern . '.*<\/a>/', $text, $links); 
$links = array_unique($links[0]); // Cleaning up array for next step. 

// Second, swap out all matches with a placeholder, and build restore array: 
foreach($links as $count => $link) { 
    $link_key = "xxx_{$count}_xxx"; 
    $restore_links[$link_key] = $link; 
    $text = str_replace($link, $link_key, $text); 
} 

// Third, we build a nice replacement array for the keywords: 

foreach($keywords as $keyword) { 
     $keyword_links[$keyword] = "<a href='#$keyword'>$keyword</a>"; 
} 

// Merge the restore links to the bottom of the keyword links for one mass replacement: 

$keyword_links = array_merge($keyword_links, $restore_links); 

$text = str_replace(array_keys($keyword_links), $keyword_links, $text); 

echo $text; 
関連する問題