2012-06-30 22 views
3

我想編碼一個小部件,它將來自多個來源的推文整理爲一個練習(類似的東西存在here,但是a)在那裏提供的列表選項沒有加載任何我的列表, b)這是一個有用的學習練習!)。作爲其中的一部分,我想編寫一個正則表達式來替換Twitter的句柄('@'後跟字符),並附帶一個鏈接到用戶的Twitter頁面。但是,我不希望誤報,例如,推文中的電子郵件地址。Javascript正則表達式 - 僞造後視鏡上的意外行爲

所以,舉例來說,更換應派

Hey there @twitteruser, my email address is [email protected] 

Hey there <a href="http://twitter.com/twitteruser">@twitteruser</a>, my email address is [email protected] 

通過this question的指導下,這表明,我需要在Javascript中複製負查找屁股的一些方法,我寫以下代碼:

tweetText = tweetText.replace(/(\S)[email protected]([^\s,.;:]*)/ig, function($0, $1){ 
    return $1 ? $0 + '@' + $1 : '<a href="http://www.twitter.com/' + $0 + '">@' + $0 + '</a>' 
}); 

但是,在第e三元運算符的最後一部分被觸發,$ 0包含'@'符號。這對我來說是意外的 - 因爲'@'沒有被括在圓括號中,所以我期望$ 0匹配'([^ \ s,。;:] *)' - 也就是Twitter用戶的用戶名,沒有,'@')。我可以通過使用$ 0.substring(1)來獲得所需的功能,但我想進一步理解。

有人請指出我誤解了什麼嗎?我對正則表達式很陌生,從來沒有用Javascript寫過,也沒有用過負面看法。

+0

'$ 0'一直是** **整體格局。 「$ 1」是第一個加括號的組,「$ 2」是第二個,等等。 – Pointy

回答

3

在任何情況下,而不是試圖在@之前匹配可選的非空間,並拒絕了比賽,如果你找到一個,爲什麼不只是需要一個空間(或字符串的開始)在@之前?

tweetText = tweetText.replace(
    /(^|\s)@([^\s,.;:]*)/g, 
    '$1<a href="http://www.twitter.com/$2">@$2</a>' 
); 

這不僅是簡單的,但它很可能是相當快一點過,因爲正則表達式需要考慮少得多的潛在匹配。

+0

完美,謝謝 - 我一開始考慮這樣做,但沒有意識到你可以混合特殊字符(如插入符號)與正常模式。這工作,謝謝! – scubbo

2

正如大多數regex實現標準行爲,匹配零是整個匹配(包括作爲它的一部分,任何子匹配 - 即使任何被標記爲非捕獲),那麼任何隨後的匹配被捕獲的子匹配。查看www.regular-expressions.info。例如:

console.log('hello, there'.match(/\w+(?:,) ?(\w+)/)); 

給你的陣列

["hello, there", "there"] //the first sub-match is non-capturing 

JavaScript不支持查詢的屁股,但也有模擬這個,沒有完美的,like the one I wrote。一般來說,JavaScript的REGEXP實現比其他一些語言更弱。遺漏的一些例子包括:

  • 查找屁股
  • 命名的原子團
  • 大部分修飾符(雖然主要的有有 - 全球性的,不區分大小寫和多線)
  • 關鍵,捕捉亞組的能力同時也匹配全球
+0

感謝你 - 我沒有意識到$ 0返回整場比賽,這解釋了很多! – scubbo

2

我想你可能會讓事情變得複雜得太多。試試這個檢索用戶名,然後讓你自己的幫助函數來創建標記。

var getTwitter = function (str) { 
    var re = /[^\w](@\w+)/g, 
     matches = [], 
     tweets = [] 
    while (matches = re.exec(str)) 
    tweets.push(matches[1]) 
    return tweets 
} 

演示:http://jsfiddle.net/elclanrs/gLvX4/

+0

感謝此 - 我覺得我需要負面lookbehinds的原因是,有時(實際上,經常)的用戶名標籤將出現在文本的開始,這個例子沒有抓住(雖然,公平地說,我在我的例子中沒有包括這一點)。如果有某種匹配「非單詞字符或字符串開頭」的方式,那將是完美的,但我不認爲/ [^ \ w | ^] /會像我希望的那樣行事。 – scubbo

+1

@scubbo:有:((^ | \ W)'。請參閱我的答案以獲取完整示例。 –

+0

是的,正則表達式可能會更好... – elclanrs

0

你太過於複雜了,沒那麼複雜。您可以在一個單一的代碼行做的一切一次,只是這樣做\[email protected](\w+)

現場演示http://jsfiddle.net/Victornpb/Wugvd/

//make twitter username links 
function linkTwitterNames(elm){ 
    elm.innerHTML = elm.innerHTML.replace(/\[email protected](\w+)/g, ' <a class="twitter" href="http://twitter.com/$1" target="_blank">@$1</a>'); 
}