非捕获组和捕获组 - 正确的方法

Non-Capturing and Capturing Groups - The right way

我正在尝试匹配一行文本中以特定字符串开头的元素数组。例如,匹配以下文本中的 all pets

fruits:apple,banana;pets:cat,dog,bird;colors:green,blue

/(?:pets:)(\w+[,|;])+/g**

使用给定的正则表达式我只能匹配最后一个词 "bird"

任何人都可以帮助我了解使用非捕获组和捕获组的正确方法吗?

谢谢!

首先说一下捕获组和非捕获组:

  • (?:...) 非捕获版本,你正在寻找这个值,但不需要它
  • () 捕获版,你要这个值!您正在寻找它

所以:

(?:pets:) 您正在搜索 "pets" 但不想捕捉它,在那之后,您想要捕捉(如果我理解的话):

所以试试 (?:pets:)([a-zA-Z,]+); ...您正在搜索 "pets:"(但不想要它!)并在第一个“;”处停止(也不想)。

结果是: 第 1 场:猫、狗、鸟

更好的解决方案是 1 场比赛 == 1 只宠物。

因为你想让每只宠物单独比赛,而且你正在使用 PCRE \G,正如 Wiktor 所建议的,一个不错的选择:

(?:pets:)|\G(?!^)(\w+)(?:[,;]|$)

解释:

  • 第一个选择(?:pets:) 找到模式的开始
  • 第二选择\G(?!^)(\w+)(?:[,;]|$)
    • \G 断言位置在上一个匹配的末尾或第一个匹配的字符串的开头
    • Negative Lookahead (?!^) 断言正则表达式在字符串的开头不匹配
    • (\w+) 匹配宠物
    • 非捕获组(?:[,;]|$)用作定界符(匹配列表中的单个字符,;(区分大小写)或$断言字符串末尾的位置

Perl 代码示例:

use strict;
use Data::Dumper;

my $str = 'fruits:apple,banana;pets:cat,dog,bird;colors:green,blue';
my $regex = qr/(?:pets:)|\G(?!^)(\w+)(?:[,;]|$)/mp;
my @result = ();

while ( $str =~ /$regex/g ) {
    if ( ne '') {
        #print "\n";
        push @result, ;
    }
}
print Dumper(\@result);