为什么在正则表达式中插入点之前捕获组中断?
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:25387
TR: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
给定以下正则表达式,其目标是捕获捕获组中项目之前的文本:
/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:25387
TR: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