正则表达式中如何从字符组中排除某个字符?

3

我有一个响应:

MS1:111980613994
124 MS2:222980613994124

我有以下正则表达式:

MS\d:(\d(?:\r?\n?)){15}

根据正则表达式,"(?:\r?\n?)" 部分应该让它匹配组但不捕获它(这样我就可以从组中得到连续的值)。
问题是对于 "MS1:xxx",它会匹配 [CR][LF] 并将其包括在组中。它应该从捕获中排除...
请帮忙解决。

1
你应该指明你正在使用哪种正则表达式匹配实现(例如Perl,PCRE,PHP,JavaScript,.Net等)。 - Tim Sylvester
4个回答

4

(?:...)语法并不意味着被括号包围的模式将从任何捕获组中排除。

它只意味着由(?:...)形成的组将成为一个非捕获组,而不是一个新的捕获组。

换句话说:

  • (?:...)仅仅是分组
  • (...)有两个功能:既分组,又捕获

捕获组捕获由它们所包含的模式匹配的所有文本,甚至匹配嵌套组的部分(无论它们是否捕获)。

示例

使用正则表达式...

.*(l.*(o.*o).*l).*

...这里有两个捕获组。如果我们将其与hello world匹配,我们将得到以下捕获:

  • 1:lo worl
  • 2:o wo

请注意,组2捕获的文本也被组1捕获。

如果我们将内部组改为非捕获...

.*(l.*(?:o.*o).*l).*

...第1组的捕获内容不会被改变(当匹配同一字符串时),但第2组已不存在:

  • 1: lo worl

正如您所看到的,如果非捕获组被包含在一个捕获组中,那么包围捕获组将捕获与非捕获组匹配的字符。

它们是用来干什么的?

非捕获组的目的不是将内容从其他捕获组中排除,而是作为一种方式来分组操作而不进行捕获。

例如,如果要重复一个子字符串,可以编写(?:substring)*

我该如何解决我的实际问题?

如果您真的想忽略嵌入的\r\n,最好的方法是在第二步中将其删除。 您没有说明使用的编程语言,但类似这样的代码(Python)应该可以起作用:

s = re.sub(r'[\r\n]', '', s)

0

0
也许你在这里想要做的是将 [CR][LF] 匹配部分放在捕获组之外,类似于:MS\d:(\d){15}(?:\r?\n?)

除非15位数字中可以散布换行符,否则您不需要在这种情况下对换行符进行分组。 - Tim Sylvester

-2

如何看待MS\d:(?:(\d)\r?\n?){15}


模式中的括号不匹配,供您参考。 - DWright

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