JavaScript 正则表达式仅选择最后一次出现

Posted

技术标签:

【中文标题】JavaScript 正则表达式仅选择最后一次出现【英文标题】:JavaScript regexp select only last occurrence 【发布时间】:2015-08-14 13:20:44 【问题描述】:

只选择最后一次出现

我正在尝试选择最后一个单词(直到空格),它们位于最后一个 white space@ 字符之后。

以下是我的字符串

hello hi @why helo @blow but @name             // capture: name
hello hi @why helo @blow but name@name         // capture: blow

还有另一个字符串

@blow but not know how to resolve this         // capture: blow

这里最后出现的是第一个单词blow,只选择单词后面的@(显然第一个单词中没有空格)。

我试过这个:https://regex101.com/r/pG1kU1/1

【问题讨论】:

是否使用捕获组进行选择? 不,我在光标时选择字符串,单击该段落左侧的所有字符串将被选中并找到最后一个空格和字符串后的@。 【参考方案1】:
(?:^| )@([^@\s]+)(?!.*?\s@\w+.*$)

你可以试试这个。查看演示。

https://regex101.com/r/pG1kU1/3

【讨论】:

whitespace@ 不捕获。我只需要最后一次出现在whitespace@ 之后的词。【参考方案2】:

作为替代方案,这样的事情怎么样?

var strings = [
    'hello hi @why helo @blow but @name',
    'hello hi @why helo @blow but name@name',
    '  hello   hi   @why   helo    @blow    but    name@name  ',
    '@blow but not know how to resolve this',
    '  @blow   but   not   know   how   to   resolve   this',
    'tada',
    '    ',
    ''
];

var wanted = strings.map(function (element) 
    var found = 'not found';
    
    element.split(/\s+/).reverse().some(function (part) 
        if (part.charAt(0) === '@') 
            found = part.slice(1);
            
            return true;
        
    );
    
    return found;
);

document.getElementById('out').textContent = wanted.join('\n')
<pre id='out'></pre>

没有复杂的正则表达式,易于理解和改变行为。确实需要 ES5 或 shims 但并不大。

【讨论】:

是的,没错,但我想在输入的单词后根据@显示下拉列表。 这个方法也没有问题。【参考方案3】:

您可以简单地使用负前瞻:

@[^@]\w*(?!.*@[^@]\w*)

regex101 demo.

(?:) 表示其中的正则表达式不能在该点之后出现。所以这个正则表达式指出,在匹配的项目之后,你不能在它旁边找到另一个 @-thing。这意味着它显然是最后一个@-东西。

请注意,对于这种情况:

@blow but not know how to resolve this@
^                                     ^
|                                     |
will match this one                   |
        because this is not a valid @/

@blow 被选中,因为@ - 根据您的正则表达式需要至少一个字符。如果要匹配@部分,需要修改为:

@[^@]?\w*(?!.*@[^@]?\w*)

或者更高效

@[^@]?\w*(?!.*@)

如果@ 必须以字符串开头或空格开头,则可以使用单词边界\B

\B@[^@]?\w*(?!.*\B@[^@]?\w*)

regex101 demo

【讨论】:

第二行我需要捕获blow 而不是name 对不起,效果不好,没有选择我需要的所有三行,谢谢你的帮助。 @S͢kyD͢ream:忘记了gmiflags,现在应该可以使用了。【参考方案4】:

最简单的答案:

/\B@[^@]\w*(?!.*?\s@)/

见DEMO

【讨论】:

第二行我需要捕获blow 而不是name @karthikmanchala:你不应该在前瞻中使用单词边界吗? @CommuSoft 在前瞻中不需要。\s 在这里更精确。你能想到为什么吗? :P 是的,因为它不再是字符串的开头。但是\B 不等于(^|\s|$),例如它也匹配$ @S͢kyD͢ream 很高兴知道它有帮助.. :)【参考方案5】:
/(?:^|\s)(@[^@]\w*)(?!.*\s@)/

应该有效;你的话将是第一次捕获。在支持lookbehinds的语言中,您可以这样做

/(?<=^|\s)@[^@]\w*(?!.*\s@)/

并让整个捕获成为您所寻求的;然而这在 javascript 中是不可能的。

如果您对仅仅一个分词而不一定是空格感到满意,这也可以:

/\b@[^@]\w*(?!.*\s@)/

我们的想法是通过积极的前瞻性检查,在我们的比赛之后没有进一步的@word

【讨论】:

以上是关于JavaScript 正则表达式仅选择最后一次出现的主要内容,如果未能解决你的问题,请参考以下文章

实验楼 正则表达式基础

正则表达式:匹配字符的第一次出现

必须通过剥离符号 ^ 字符的最后一次出现以通过正则表达式提取结束来提取单词的开头

正则表达式在匹配字符串之后查找最大数字的最后一次出现

最后一次出现 : 和 .tst 之间的文本的正则表达式

JavaScript重点记忆