2015-10-16 201 views
-1

我有下面的代碼,它應該使純文本鏈接可點擊。但是,如果有多個鏈接,它只會替換最後一個鏈接。preg_match_all和foreach只替換最後的匹配

代碼:

$nc = preg_match_all('#<pre[\s\S]*</pre>#U', $postbits, $matches_code); 
foreach($matches_code[0] AS $match_code) 
{ 
    $match = null; 
    $matches = null; 
    $url_regex = '#https?://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?[^<\.,:;"\'\s]+#'; 
    $n = preg_match_all($url_regex, $match_code, $matches); 
    foreach($matches[0] AS $match) 
    { 
     $html_url = '<a href="' . $match . '" target="_blank">' . $match . '</a>'; 
     $match_string = str_replace($match, $html_url, $match_code); 
    } 
    $postbits = str_replace($match_code, $match_string, $postbits); 
} 

結果:

http://www.google.com 

http://www.yahoo.com 

http://www.microsoft.com/ <-- only this one is clickable 

預期結果:

http://www.google.com

http://www.microsoft.com/

我的錯誤在哪裏?

+0

什麼的'[\ S \ S]'點?這匹配一切,就像'.'。如果問題在於它不符合換行符,使用's'修飾符。 – Barmar

回答

0

我認爲你的錯誤是;

$html_url = ''; //html tags<a></a> 

而且會像這樣結束; 你應該像這樣使它充滿活力;

$html_url .= ''; //html tags<a></a> 

而且

foreach($matches[0] AS $match) 
    { 
     $html_url .= '<a href="' . $match . '" target="_blank">' . $match . '</a>'; //here, you are replacing 
     $match_string = str_replace($match, $html_url, $match_code); 
    } 
0

如果有幾個環節,只替換最後一個

哪裏是我的錯誤?

實際上,它取代了所有3個鏈接,但它每次都會替換原始字符串。

foreach($matches[0] AS $match) 
{ 
    $html_url = '<a href="' . $match . '" target="_blank">' . $match . '</a>'; 
    $match_string = str_replace($match, $html_url, $match_code); 
} 

的循環被執行3次,每次它取代在$match_code 1個鏈路並將結果$match_string分配時間。在第一次迭代中,$match_string被分配了可點擊的結果google.com。在第二次迭代中,$match_string分配有可點擊yahoo.com。但是,您剛剛替換了原始字符串,因此google.com現在不是可點擊。這就是爲什麼你只能得到你的最後一個鏈接。


有一對夫婦,你可能還需要在你的代碼來糾正的事情:

  1. 正則表達式#<pre[\s\S]*</pre>#U更好地構建爲#<pre.*</pre>#Us。類[\s\S]*通常用於JavaScript,其中沒有s標誌允許點與新行匹配。
  2. 我不明白你爲什麼使用該模式來匹配網址。我想你可以簡單地使用https?://\S+。我還會將你鏈接到一些替代品here
  3. 您正在使用2 preg_match_all()來電和1 str_replace()要求輸入相同的文本,您可以將其包含在1 preg_replace()中。

代碼

$postbits = " 
<pre> 
http://www.google.com 

http://w...content-available-to-author-only...o.com 

http://www.microsoft.com/ <-- only this one clickable 
</pre>"; 


$regex = '#\G((?:(?!\A)|.*<pre)(?:(?!</pre>).)*)(https?://\S+?)#isU'; 
$repl = '\1<a href="\2" target="_blank">\2</a>'; 

$postbits = preg_replace($regex, $repl, $postbits); 

ideone demo

的Regex

  • 來自受試者的第一個匹配位置\G始終。
  • 組1
    • (?:(?!\A)|.*<pre)匹配從字符串的beggining第一<pre標籤,或允許獲得下一個<pre標籤,如果在這個標籤中沒有發現更多的URL。
    • (?:(?!</pre>).)*)消耗<pre>標記中的任何字符。
  • 組2個
    • (https?://\S+?)相配1個URL。

Regular expression visualization