为什么在正则表达式中插入点之前捕获组中断?

Why capturing group breaks when inserting dot before it in regular expression?

给定以下正则表达式,其目标是捕获捕获组中项目之前的文本:

/cliente:[\sa-z.ñÑ0-9(),']+(?=((?:traslado|tr|giro|rut|rt)\:.*))/gmi

带有文本字符串:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

并获得成功的结果。但是,如果我在正则表达式中插入一个点,如下所示:

/cliente:.+(?=((?:traslado|tr|giro|rut|rt)\:.*))/gmi

它破坏了捕获组,产生

CLIENTE:NUBOX S.A. TRASLADO:CONSIGNACIONESRUT:25387TR:CONSIG

我需要知道为什么会这样。

您可以通过查看 Regex101 上的正则表达式调试器来了解它们匹配方式的不同。

让我解释一下每个正则表达式是如何匹配的。

让我们看一下第一个正则表达式。该正则表达式 cliente:[\sa-z.ñÑ0-9(),']+ 的第一部分最初将匹配此:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

它停在了:,但它已经走得太远了;它无法匹配前瞻。然后它必须逐个字符回溯,看看它是否可以匹配前瞻:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
...
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

现在,让我们看一下第二个正则表达式。该正则表达式的第一部分 cliente:.+ 将匹配整行:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

当然,这不会为前瞻匹配留下任何东西,所以它必须逐个字符回溯:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
...
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

因为你从不同的地方回溯,你会得到不同的结果。这种行为,尽可能匹配,就是greedy. On the other hand, you have the option to make things lazy:

/cliente:.+?(?=((?:traslado|tr|giro|rut|rt)\:.*))/gmi

这个改变后的正则表达式的第一部分 cliente:.+? 首先将尽可能少地匹配:

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

然后它会尝试匹配前瞻。此时它无法匹配,因此它向上移动一个字符并尝试再次匹配该前瞻,重复直到找到某些东西(并且 returns 匹配)或没有留下任何字符串(并且失败):

CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG
...
CLIENTE:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387TR:CONSIG