我正在尝试编写一个小部件来整理来自多个来源的推文作为练习(存在类似的东西here,但是a)在那里提供的列表选项没有加载我的任何列表,并且b)它是一个有用的学习练习!)。作为其中的一部分,我想编写一个正则表达式,用一个指向用户Twitter页面的链接替换Twitter句柄('@'后跟字符)。但是,我不希望误报,例如,推文中的电子邮件地址。
因此,例如,替换应该发送
Hey there @twitteruser, my email address is address@gmail.com
到
Hey there <a href="http://twitter.com/twitteruser">@twitteruser</a>, my email address is address@gmail.com
在this question的引导下,我建议我需要一些在Javascript中复制负面观察的方法,我写了以下代码:
tweetText = tweetText.replace(/(\S)?@([^\s,.;:]*)/ig, function($0, $1){
return $1 ? $0 + '@' + $1 : '<a href="http://www.twitter.com/' + $0 + '">@' + $0 + '</a>'
});
但是,在触发三元运算符的最后部分的情况下,$ 0包含“@”符号。这对我来说意外 - 因为'@'没有括在括号中,我期望$ 0匹配'([^ \ s,。;:] *)' - 即Twitter用户的用户名(之后,和不,'@')。我可以使用$ 0.substring(1)获得所需的功能,但我想进一步理解。
有人可以指出我误解了什么吗?我对Regexs很陌生,从来没有用Javascript编写它们,也没有使用过负面的后视镜。
答案 0 :(得分:3)
在任何情况下,不是试图在@
之前匹配可选的非空格,而是在找到匹配时拒绝匹配,为什么不在此之前只需要一个空格(或字符串的开头) @
?
tweetText = tweetText.replace(
/(^|\s)@([^\s,.;:]*)/g,
'$1<a href="http://www.twitter.com/$2">@$2</a>'
);
这不仅更简单,而且可能会更快,因为正则表达式需要考虑更少的潜在匹配。
答案 1 :(得分: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实现通常比其他一些语言弱。遗漏的一些例子包括:
答案 2 :(得分:2)
我认为你可能会使事情变得太复杂。尝试这个来检索用户名,然后创建自己的帮助函数来创建标记。
var getTwitter = function (str) {
var re = /[^\w](@\w+)/g,
matches = [],
tweets = []
while (matches = re.exec(str))
tweets.push(matches[1])
return tweets
}
答案 3 :(得分:0)
你过度复杂,并不复杂。您可以在一行代码上执行一次,只需执行此操作\W@(\w+)
现场演示http://jsfiddle.net/Victornpb/Wugvd/
//make twitter username links
function linkTwitterNames(elm){
elm.innerHTML = elm.innerHTML.replace(/\W@(\w+)/g, ' <a class="twitter" href="http://twitter.com/$1" target="_blank">@$1</a>');
}