我有一個用戶提交的內容負載。它是HTML,可能包含URL。其中一些將是<a>
已經(如果用戶是好的),但有時用戶懶惰,只需鍵入www.something.com或最好http://www.something.com。需要一個很好的正則表達式來將URL轉換爲鏈接,但只保留現有鏈接
我找不到一個體面的正則表達式來捕獲URL,但忽略立即在雙引號或'>'右邊的那些。任何人都有一個?
我有一個用戶提交的內容負載。它是HTML,可能包含URL。其中一些將是<a>
已經(如果用戶是好的),但有時用戶懶惰,只需鍵入www.something.com或最好http://www.something.com。需要一個很好的正則表達式來將URL轉換爲鏈接,但只保留現有鏈接
我找不到一個體面的正則表達式來捕獲URL,但忽略立即在雙引號或'>'右邊的那些。任何人都有一個?
Jan Goyvaerts,RegexBuddy的創建者,擁有written a response給Jeff Atwood的博客,該博客解決Jeff提供的問題並提供了一個很好的解決方案。
\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$]
爲了忽略發生的旁邊的一個「或>,您可以添加(?<![">])
的正則表達式的開始比賽,所以你得到
(?<![">])\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$]
這將匹配完整地址(http://.. )以及與WWW或FTP起始地址 - 你的運氣與地址一樣ars.userfriendly.org ...
無恥插頭:你可以看看這裏(regular expression replace a word by a link)爲靈感
。這個問題要求用某個鏈接替換某個詞,除非已經存在鏈接。所以你遇到的問題或多或少是一回事。
您只需要一個匹配URL的正則表達式(代替單詞)。最簡單的假設是這樣的:一個URL(可選)以"http://"
,"ftp://"
或"mailto:"
開頭,只要沒有空格字符,換行符,標記括號或引號就可以持續。
要小心,長的正則表達式在前面。不區分大小寫應用。
(href\s*=\s*['"]?)?((?:http://|ftp://|mailto:)?[^.,<>"'\s\r\n\t]+(?:\.(?![.<>"'\s\r\n])[^.,!<>"'\s\r\n\t]+)+)
被警告 - 這也將匹配在技術上無效的網址,它可以識別things.formatted.like.this作爲URL。如果它太不靈敏,這取決於你的數據。如果你有例子返回誤報,我可以微調正則表達式。
正則表達式將產生兩個匹配組。第2組將包含匹配的東西,這很可能是一個URL。組1將包含一個空字符串或'href="'
。你可以用它作爲一個指標,表明這個匹配發生在裏面現有鏈接的href參數,你不必觸摸那個。
一旦你確認此做正確的事你大部分時間(與用戶提供的數據,你永遠無法確定),你可以做其餘的兩個步驟,正如我在另議它問題:
<a>
標籤。<a>
標籤,去掉最裏面的一個要跳過現有的只使用一個向後看 - 添加(?<!href=")
到你的正則表達式的開始,所以它看起來是這樣的:
/(?<!href=")http://\S*/
顯然,這不是對找到所有類型的URL的完整的解決方案,但是這應該解決您與現有搞亂的問題。
我做了少許修改包含在原來的答案正則表達式:
(?<![.*">])\b(?:(?:https?|ftp|file)://|[a-z]\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$]
,讓更多的子域,並可以運行在標籤更爲全面檢查。若要將此PHP的預浸料代替,你可以使用:
$convertedText = preg_replace('@(?<![.*">])\b(?:(?:https?|ftp|file)://|[a-z]\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$]@i', '<a href="\0" target="_blank">\0</a>', $originalText);
注意,我刪除@從正則表達式,爲了使用它作爲一個的preg_replace分隔符。無論如何,@將很少用在URL中。
很明顯,你可以修改替換文本,並刪除目標=「_空白」,或添加相對=「nofollow」等
希望有所幫助。
這條線程比較古老,但我在處理自己的問題時遇到了它:也就是說,將任何網址轉換爲鏈接,但不要將任何已經存在於錨定標記中的網址留下。過了一會兒,這是什麼彈出:
(?!(?!.*?<a)[^<]*<\/a>)(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$]
用下面的輸入:
http://www.google.com
http://google.com
www.google.com
<p>http://www.google.com<p>
this is a normal sentence. let's hope it's ok.
<a href="http://www.google.com">www.google.com</a>
這是一個preg_replace函數的輸出:
<a href="http://www.google.com" rel="nofollow">http://www.google.com</a>
<a href="http://google.com" rel="nofollow">http://google.com</a>
<a href="www.google.com" rel="nofollow">www.google.com</a>
<p><a href="http://www.google.com" rel="nofollow">http://www.google.com</a><p>
this is a normal sentence. let's hope it's ok.
<a href="http://www.google.com">www.google.com</a>
只是想回貢獻爲了節省一些時間。
if (preg_match('/\b(?<!=")(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[A-Z0-9+&@#\/%=~_|](?!.*".*>)(?!.*<\/a>)/i', $subject)) {
# Successful match
} else {
# Match attempt failed
}
我剛開始添加的=在(?])不會打破link(不帶引號的錨標記)。尼斯正則表達式順便說一句:) – Joel 2010-06-29 10:41:41
@Joel:你確定你希望lookbehind意思是「斷言在字符串中當前位置之前不可能匹配點,星號,引號或關閉角括號」嗎? – 2012-04-13 16:44:16