我想捕获@usernames的提及。用户名具有以下规则:
所以,我想出了这个:
/(?:^|\s)(@)(?!\.)(?!.*\.\.)(?!.*\.[\s|$])([a-z0-9\.]+)(?:\s|$)/gm;
这应该意味着:
(?:^|\s) starting at start of line, or with a whitespace
(@) having a @
(?!\.) name not starting with a dot
(?!.*\.\.) not containing two adjacent dots (..)
(?!.*\.[\s|$]) not ending with a dot (yes this sucks)
([a-z0-9\.]+) allowed chars
(?:\s|$) ending at EOL or whitespace
作为一个具有正则表达式的完整菜鸟,我很高兴看到这是如何使用长的多行测试字符串执行的。 但后来我尝试了最简单的测试字符串,如:
@foo @bar I hate you both.
在这种情况下foo被捕获,但bar不是。我想,即使我使用非捕获组,@foo
也会占用以下空格,因此@bar
在(?:^|\s)
处失败。
如何编辑此正则表达式以使其正常工作?
请不要建议完全不同的@mention正则表达式,我可以很好地搜索它们,因为还有其他问题。我只想让它工作,并知道它为什么没有。
答案 0 :(得分:2)
通常,您在这里遇到的问题是您在单词的开头和结尾使用了捕获组,这意味着这些字符会从进一步的RegEx匹配中消耗掉。
这是因为你这样做:(?:...)
。
相反,您可以使用一类特殊的捕获组,它们不使用名为Lookahead的字符:(?=...)
在RegEx中,有Lookbehind AND Lookahead,它分别在RegEx之前和之后进行检查。对你的问题的完美答案将使用lookbehind作为字符串(?<=^|\s)
的开头,并使用lookahead作为字符串(?=\s|$)
的结尾。不幸的是,在Javascript中,不支持Lookbehind,但是为了满足您的特定需求,我们可以解决这个问题。
如果我们确保不捕获用户名末尾的尾随空格,那么它可以用于匹配您在RegEx开头定义的捕获组。这是代码:
(?:^|\s)(@)(?!\.)(?!\S*\.\.)(?!\S*\.[\s|$])([a-z0-9\.]+)(?=\s|$)
注意除了&#39; =&#39;之外,一切都差不多。在最后一节,&#39; \ S&#39;在&#39;没有以点为结尾&#39;部分和&#39;不包含两个相邻的点&#39;,您在下面的评论中找到了这些点。
可以找到结果here。不幸的是,这将返回与其中的空间完全匹配的&#34; @ bar&#34;,但该匹配的子组看起来仍然很好。
请告诉我这是否有帮助!
答案 1 :(得分:0)
答案 2 :(得分:0)
有两种类型的提及,像 facebook 这样的有空格和没有像 twitter 这样的空格:
没有空间(如推特):
(?:^|\\s|$|[.])@[\\p{L}0-9_]*
对于空间(如facebook):
@[[\\p{L}0-9_]*(\\s)?[\\p{L}0-9_]*]*