2013-02-21 54 views
4

所以我正在構建一個小型CMS,並且我想避免在內容編輯器中允許使用HTML。出於這個原因,我想檢測文本中的原始URL以及支持類似BB的標籤,以獲得更好的定製。URL檢測和BB風格標籤(正則表達式,前瞻性問題)

www.example.com 
[link http://www.example.com]Click me[/link] 

不幸的是,我是相當新的正則表達式,我似乎無法得到這個工作。我在字符串上運行兩個正則表達式:第一個檢測原始URL,第二個BB類URL。後者似乎工作得很好,第一個干擾,然後轉換包裹在標籤中的URL。

我從一段代碼開始,找到here並做了一些補充。

這是對非標記網址的代碼:

/* don't match URLs preceeded by '[link ' */ 
(?<!\[link\s) 
(
    /* match all combinations of protocol and www. */ 
    (\bhttps?://www\.|\bhttps?://|(?<!//)\bwww\.) 

    /* match URL (no changes made here) */ 
    ([^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))) 

    /* but don't match if followed by [/link] - THIS DOESN'T WORK */ 
    (?!\[/link\]) 
) 

負向後看前www.是那裏,因爲/不是一個字符,而沒有它像

[link http://www.example.com]example[/link] 

仍然會在http://後匹配。

上述正則表達式產生以下的比賽(與http://gskinner.com/RegExr/測試,比賽都在大膽我不得不http://後添加空格,因爲我不能發佈更多的網址。):

WWW .example.com的
HTTP:// www.example.com
HTTP:// example.com
[鏈接http://www.example.com]no問題1 [/鏈接]
[鏈接www.example.com]沒問題2 [/鏈接]
[鏈接http://www.example.com]http://www.example.com[/link]

我試着走動負前瞻並用括號(非常漫無目的地)玩,沒有成功。

爲了完整起見,這裏的標記匹配的正則表達式(這似乎工作):

(?:\[link\s)(\bhttps?://|\bwww\.|\bhttps?://www\.)([^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))\](.*)(?:\[/link\]) 

我敢肯定有人可以立即發現錯誤。

非常感謝!

+0

'(?!\ [/ link \])'lookahead將失敗,因爲PCRE會連續縮短前一個匹配的成功。您可能需要使URL匹配超級貪婪。嘗試'(?> ...)'使其成爲原子。 – mario 2013-02-21 15:15:16

+0

你能再詳細一點嗎?我試圖讓各個小組成爲原子,但沒有成功(我不確定我是否完全理解原子組)。 – psalz 2013-02-22 11:42:46

回答

0

我已經採取了你的正則表達式,用你給出的例子試圖使它成爲正則表達式,並試圖使它正常工作。

一步一步:

1)原正則表達式:http://regexr.com?33snj。爲什麼這個正則表達式的[/鏈接]也匹配的問題是在URL匹配位:

[^\s()<>]+ 

這也將匹配開放括號字符「[」,因此匹配在遇到[/鏈接不會停止]位。有人可能會認爲[字符是一個有效的URI字符,但這只是在罕見的條件下(請參閱this stackoverflow以獲取更多信息)。

2)我決定繼續與您正則表達式,倒是開括號字符到否定的字符序列:

[^\s()<>[]+ 

這將讓你成爲另一個問題。見http://regexr.com?33snp。由於回溯引擎,現在在最後找到一種解決負面預測的方法。

3)一旦你將URL匹配組原子化(通過將?>添加到捕獲組的開始處),引擎就會停止回溯,並且我們已經達到了期望的結果。

(?<!\[link\s)((\bhttps?://www\.|\bhttps?://|(?<!//)\bwww\.)(?>[^\s()<>[]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))(?!\[/link\])) 

看到它在行動http://regexr.com?33sns

+0

我實際上也嘗試過爲反義字符添加左括號,但由於擔心某些URL不再被檢測到(除了因爲我沒有使捕獲組原子化而不工作),所以停止繼續此解決方案 - 但是,通過您提供的鏈接,我現在對此解決方案非常滿意。非常感謝! – psalz 2013-02-24 11:21:11

+0

我明白這個問題。這個URL匹配很簡單,但是完成這項工作。我不會只允許括號。相反,我會去認識IPv6地址的URL。 – 2013-02-24 19:31:54

+0

還有我不知道你爲什麼需要這個(:\([\ W \ d] + \)|([^ [:PUNCT:] \ s] | /?))的URL匹配有點落後。您可能需要一段時間來研究更好的url匹配模式。只是要小心不要在括號中包括括號:) – 2013-02-24 19:36:05