【问题标题】:lookhehind assertion length errorlookhehind 断言长度错误
【发布时间】:2018-07-15 15:41:39
【问题描述】:

我在 pcre 中尝试这条正则表达式行时遇到了一个奇怪的错误:

^(.*[ \-_])?(SS|SSN|SIN|SSIN|SSNSIN|((SOC(IAL)?[_\- ]?SEC(URITY)?|SOC)[_\- 
]?(DISABILITY)?[_\- ]?(INSURANCE)?(NUMBER|NUM|NO|NBR|NR)?))([ \-_].*)?(?<!
(CD|DT|F))$

错误信息是: 您的表达导致了未处理的错误: 后视断言不是固定长度 - 偏移量:158

我试图用这个来修复它,但它不起作用:

^(.*[ \-_])?(SS|SSN|SIN|SSIN|SSNSIN|((SOC(IAL)?[_\- ]?SEC(URITY)?|SOC)[_\- 
]?(DISABILITY)?[_\- ]?(INSURANCE)?(NUMBER|NUM|NO|NBR|NR)?))([ \-_].*)?(?:(?
<!(CD|DT))|(?<!F))$

请帮忙!

【问题讨论】:

  • 我遵循了stackoverflow.com/questions/3796436/… 中的解决方案,但没有奏效。我猜他们的情况是 ?
  • 这不是一个奇怪的错误,它在错误消息中正确地说明了这一点。您的后视需要 固定 长度(而不是可变长度)。这意味着您的后视 (?&lt;!(CD|DT|F)) 需要是 1 个或 2 个字符,但不能同时是两者。目前,(?&lt;!(CD|DT|F)) 的长度为 2 (CD, DT) 长度为 1 (F)。您不能在 PCRE 中执行此操作。此规则的唯一例外是当您使用 0 长度断言时,例如 ^$ 等。
  • 感谢您的评论。我知道这个错误的原因,但只是不知道如何解决它。它必须在 pcre 中完成。你有什么解决办法吗?
  • @XinJin 你能给我们提供几个示例字符串吗?这样做可以让我们提供正确的方法,但您可能需要使用带有 if 子句的 (*FAIL) 之类的控制动词
  • @XinJin:你只需要删除捕获组:(?&lt;!(CD|DT|F)) => (?&lt;!CD|DT|F)

标签: regex pcre


【解决方案1】:

说后视必须具有固定长度并不完全适用于 pcre。如果你不能写(?&lt;!ab*c)(?&lt;!(AB|BC|C))(?&lt;!(AB|BC|CD))之类的东西,你可以写这样的东西:

(?<!CD|DT|F)

仅当它包含一个交替(未包含在组中)且交替的每个分支都具有固定长度时,才允许使用可变长度的lookbehind。

结论,您后面的问题是组,而不是每个分支之间的不同字符数。

【讨论】:

    【解决方案2】:

    将您的后视一个接一个 (AND),而不是交替 (OR):(?&lt;!F)(?&lt;!CD)(?&lt;!DT),像这样:

    ^(.*[ \-_])?(SS|SSN|SIN|SSIN|SSNSIN|((SOC(IAL)?[_\- ]?SEC(URITY)?|SOC)[_\- ]?(DISABILITY)?[_\- ]?(INSURANCE)?(NUMBER|NUM|NO|NBR|NR)?))([ \-_].*)?(?<!F)(?<!CD)(?<!DT)$

    由于环视是“零宽度断言”,根本不会将当前匹配位置向右移动,因此您可以简单地将它们一个接一个地放置。

    https://regex101.com/r/m95Jrs/1/

    【讨论】:

    • 可简写为(?&lt;!CD|DT)(?&lt;!F)
    • 太棒了!非常感谢,伙计!
    【解决方案3】:

    lookbehind 必须匹配一个固定长度的字符串。 regular-expression.info 包含这样的解释:

    坏消息是大多数正则表达式风格不允许您在后视中使用任何正则表达式,因为它们不能向后应用正则表达式。正则表达式引擎需要能够在检查回溯之前计算出要退回多少个字符。在评估后视时,正则表达式引擎确定后视内正则表达式的长度,后退主题字符串中的许多字符,然后在后视内从左到右应用正则表达式,就像使用普通正则表达式一样。

    对于(CD|FT|F) 模式,它不能这样做,因为它不知道是返回 2 个字符还是 1 个字符。

    解决方法是分两步进行检查。从正则表达式中取出负面的后视。如果您找到匹配项,请进行额外检查以查看其中一个模式是否位于末尾,并将其从结果集中删除。

    【讨论】:

    • 这就是我所做的,但它不起作用:(?:(?
    • 你不能用|连接两个否定的lookarounds。
    • @sweaver2112 提供了一个很好的解决方案。谢谢大家的回复。祝你有美好的一天!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2018-05-19
    • 2014-09-27
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多