奇数正则表达式行为 - 仅匹配第一个和最后一个捕获组

问题描述 投票:7回答:4

我正在尝试编写一个与逗号分隔的单词列表匹配并捕获所有单词的正则表达式。这条线应该匹配   apple , banana ,orange,peanut 和捕获应该是applebananaorangepeanut。为此,我使用以下正则表达式:

^\s*([a-z_]\w*)(?:\s*,\s*([a-z_]\w*))*\s*$

它成功地匹配了字符串,但突然间只有applepeanut被捕获。在C#和Perl中都可以看到这种行为。因此,我假设我遗漏了有关正则表达式匹配如何工作的事情。有任何想法吗? :)

c# regex perl capture
4个回答
4
投票

match.Groups[2].Value给出的值只是第二组捕获的最后一个值。

要查找所有值,请查看match.Groups[2].Captures[i].Value,在这种情况下,i的范围从02。 (以及第一组的match.Groups[1].Value。)

(+1问题,我今天学到了一些东西!)


3
投票

试试这个:

string text = "   apple , banana ,orange,peanut";

var matches = Regex.Matches(text, @"\s*(?<word>\w+)\s*,?")
        .Cast<Match>()
        .Select(x => x.Groups["word"].Value)
        .ToList();

2
投票

你是repeating your capturing group,在每次重复比赛时都会覆盖以前的内容。因此,最后只有第二个捕获组的最后一个匹配。

您可以将第二个捕获组更改为

^\s*([a-z_]\w*)((?:\s*,\s*(?:[a-z_]\w*))*)\s*$

然后结果将是你的第二组中的“香蕉,橙子,花生”。我不确定,如果你想要这个。

如果要检查字符串是否具有该模式并提取每个单词。我会分两步完成。

  1. 用正则表达式检查模式。
  2. 如果模式正确,请删除前导和尾随空格并在\s*,\s*上拆分。

2
投票

简单的正则表达式:

(?:^| *)(.+?)(?:,|$)

说明:

?:    # Non capturing group
^| *  # Match start of line or multiple spaces
.+    # Capture the word in the list, lazy
?:    # Non capture group
,|$   # Match comma or end of line 

注意:Rublular是一个很好的网站,用于测试这种事情。

© www.soinside.com 2019 - 2024. All rights reserved.