非捕获组和捕获组 - 正确使用方法

3

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

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

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

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

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

谢谢!


1
/pets:([^;]*)/这个怎么样? - undefined
你的正则表达式是用哪种语言实现的? - undefined
你不能将每个宠物分别捕获到不同的组,因为你只有一个组。你可以做的是将所有宠物都捕获到同一组中,例如 pets:((?:\w+[,;])+) - undefined
1
正则表达式的风格是什么?你可以使用pets:(?:(\w+)(?:[,;]|$))+在.NET正则表达式中访问第1组捕获集合来获取所需内容;否则,在PCRE、Java和Onigmo中,你可以依赖于\G(?:\G(?!^)(?:[,;]|$)|pets:)(\w+)(并获取第1组的值)。 - undefined
我目前正在使用PCRE,目标是在匹配中获取每个宠物。 - undefined
2个回答

7

首先,让我们谈一下捕获组和非捕获组:

  • (?:...) 非捕获版本,你想要这些值,但不需要它
  • () 捕获版本,你想要这些值!你在搜索它

所以:

(?:pets:) 你搜索"pets",但不想捕获它,在那之后,你想要捕获(如果我理解正确):

因此尝试 (?:pets:)([a-zA-Z,]+); ... 你正在搜索"pets:"(但不想要它!)并停在第一个";"(也不想要它)。

结果是:匹配1:cat,dog,bird

存在一种更好的解决方案,即每次匹配1个宠物。


4
(?:pets) 相当于 pets - undefined

3

如果您希望每个宠物都在单独的比赛中,并且您正在使用PCRE,则如Wiktor建议的那样,\G 是一个不错的选择:

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

解释:

  • 1st Alternative (?:pets:)用于找到模式的开头
  • 2nd Alternative \G(?!^)(\w+)(?:[,;]|$)
    • \G断言前面的匹配结束位置,或在第一次匹配时断言字符串的开始位置
    • Negative Lookahead (?!^) 断言Regex不会在字符串的起始处匹配
    • (\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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接