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

时间:2018-05-28 17:59:17

标签: regex regex-group

我试图在一行文本中匹配一个特定字符串前面的元素数组。例如,在下面的文字中匹配所有宠物

  

水果:苹果,香蕉; 宠物:猫,狗,鸟;颜色:绿色,蓝色

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

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

有人可以帮助我理解使用非捕获和捕获组的正确方法吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

首先,我们来谈谈捕获和非捕获组:

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

所以:

(?:pets :)你在寻找“宠物”但不想抓住它,在那之后,你想捕捉(如果我理解的话):

所以试试(?:pets :)([a-zA-Z,] +); ...你正在寻找“宠物:”(但不想要它!)并停在第一个“;” (并且也不要这样)。

结果是: 比赛1:猫,狗,鸟

1匹配== 1宠物存在更好的解决方案。

答案 1 :(得分:2)

由于您希望让每只宠物分开进行比赛,并且您正在使用PCRE \G,正如Wiktor所建议的那样,是一个不错的选择:

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

说明:

  • 第一个替代(?:pets:)以找到模式的开头
  • 第二个替代\G(?!^)(\w+)(?:[,;]|$)
    • \G在上一场比赛结束时或第一场比赛的字符串开头处断言位置
    • 否定前瞻(?!^)断言正则表达式在字符串的开头不匹配
    • (\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 ($1 ne '') {
        #print "$1\n";
        push @result, $1;
    }
}
print Dumper(\@result);