Javascript正则表达式 - 假装背后的意外行为

时间:2012-06-30 23:30:17

标签: javascript regex lookbehind negative-lookbehind

我正在尝试编写一个小部件来整理来自多个来源的推文作为练习(存在类似的东西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编写它们,也没有使用过负面的后视镜。

4 个答案:

答案 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
}

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

答案 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>');
}