【问题标题】:Non-Capturing and Capturing Groups - The right way非捕获组和捕获组 - 正确的方法
【发布时间】:2018-05-28 17:59:17
【问题描述】:

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

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

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

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

谁能帮我理解使用非捕获组和捕获组的正确方法?

谢谢!

【问题讨论】:

  • /pets:([^;]*)/ 怎么样?
  • 你的正则表达式是什么语言的?
  • 您不能在单独的组中捕获每只宠物,因为您只有 1 个组。您可以做的就是将它们全部捕获在同一个组中,例如pets:((?:\w+[,;])+)
  • 什么是正则表达式?您应该通过访问第 1 组捕获集合在 .NET 正则表达式中使用 pets:(?:(\w+)(?:[,;]|$))+ 获得所需的内容,否则,在 PCRE、Java、Onigmo 中,您可以依赖 \G(?:\G(?!^)(?:[,;]|$)|pets:)(\w+)(并获得第 1 组值)。
  • 我目前正在使用 PCRE,目标是让每只宠物都参加比赛

标签: regex regex-group


【解决方案1】:

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

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

所以:

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

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

结果是: 匹配1:猫,狗,鸟

更好的解决方案是 1 匹配 == 1 只宠物。

【讨论】:

  • (?:pets) 等价于pets
【解决方案2】:

由于您想让每只宠物都参加单独的比赛并且您正在使用 PCRE \G,正如 Wiktor 所建议的那样,这是一个不错的选择:

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

解释:

  • 1st Alternative (?:pets:) 找到模式的开始
  • 第二选择\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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    相关资源
    最近更新 更多