我的正则表达式几乎完全符合我的要求:\.?(\w+[\s|,]{1,}\w+[\s|,]{1,}\w+){1}\.?
意思是它捕获连续3个单词的发生率,除了空格和逗号之外没有任何东西(仅限句子的部分)。但是我希望这能匹配句子中每个 3个单词的实例。
所以在这个非常简单的例子中:
Hi this is Bob.
应该有2次捕获 - “嗨,这是”和“这是鲍勃”。我似乎无法弄清楚如何让regex引擎以这种方式解析整个语句。有什么想法吗?
答案 0 :(得分:2)
您不仅可以在捕获组中获取重叠文本,还可以获取重叠的匹配与捕获您需要的子串的组。
使用
(?=\b(\w+(?:[\s,]+\w+){2})\b)
请参阅regex demo
未锚定的正向前瞻测试在字符串的每个位置处的空字符串匹配。它不消耗字符,但仍然可以返回通过捕获组获得的子匹配。
正则表达式细分:
\b
- 字边界(\w+(?:[\s,]+\w+){2})
- 以,
或空格分隔的3个“单词”。
\w+
- 一个或多个字母数字符号,后跟(?:[\s,]+\w+){2}
- 包含1个或多个空格或逗号的2个序列,后跟1个或多个字母数字符号。此模式只是放在前瞻(...)
内的捕获组(?=...)
中。
单词边界在此表达式中很重要,因为\b
会阻止在内部匹配(在两个字母数字字符之间)。由于前瞻没有锚定,它会测试输入字符串中的所有位置,而\b
可以作为对可以返回匹配位置的限制。
在C#中,您只需收集所有match.Groups[1].Value
个,例如像这样:
var s = "Hi this is Bob.";
var results = Regex.Matches(s, @"(?=\b(\w+(?:[\s,]+\w+){2})\b)")
.Cast<Match>()
.Select(p => p.Groups[1].Value)
.ToList();
请参阅IDEONE demo