【问题标题】:Why capturing group breaks when inserting dot before it in regular expression?为什么在正则表达式中插入点之前捕获组中断?
【发布时间】:2016-09-23 14:17:37
【问题描述】:

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

/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

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

【问题讨论】:

  • 因为点不匹配换行符,而你的字符类中的 \s 匹配。
  • 首先,我鼓励您阅读Greedy vs Non-greedy 问题。 用贪心点加上.+ 模式替换旧模式会导致在以下情况下消耗输入字符串的所有字符正则表达式引擎到达.+。因此,通过传递此模式,您可以确定当前光标位于输入行的末尾。对于引擎,所有模式都应该成功匹配,因此它会命中下一个模式,即 + 前瞻结构。在字符串末尾没有trasladort 或...
  • ... 其他选择。所以它会回溯(后退一步)到G 之前。然后再次前瞻不匹配。它继续回溯,直到出现在TR 之前。 Lookahead 成功并且引擎满足。期间。
  • [\sa-z.ñÑ0-9(),']+.+ 之间有趣的区别在于 [\sa-z.ñÑ0-9(),']+ 不匹配冒号 :.+ 匹配。

标签: regex lookahead capturing-group


【解决方案1】:

您可以通过查看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:.+ 的第一部分将匹配整行:

客户:NUBOX S.A.TRASLADO:CONSIGNACIONESRUT:25387 TR:CONSIG

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

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

因为你从不同的地方回溯,你会得到不同的结果。这种尽可能匹配的行为是greedy另一方面,您可以选择制作东西lazy

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

这个改变的正则表达式 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:25387TR:CONSIG

【讨论】:

  • 你为什么说它失败了?使用这种模式(使其变得懒惰)我得到了我想要的 /cliente:.+?(?=((?:traslado|tr|giro|rut|rt)\:.*))|cliente:.+?/gmi 客户:nubox 。 s.a
  • @FabianOlmos 我稍微修改了措辞。现在是不是有点意思了?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 2023-03-15
  • 2011-03-31
相关资源
最近更新 更多