如何在锚定的正则表达式模式中使用负向前看?



我的web应用程序允许用户指定符合以下限制的自定义URI路径组件:

  • 所有字符必须小写
  • 长度至少为2个字符。
  • 第一个字符必须匹配[a-z]
  • 最后一个字符必须匹配[0-9a-z]
  • 其他字符必须匹配[0-9a-z_-]
  • -_字符不能连续出现2个或以上。
    • 。字符串不能包含--___--_

我已经很容易地在正则表达式中实现了前5条规则:

^[a-z][0-9_a-z-]*[0-9a-z]$

…然而,我不知道如何在单个正则表达式中实现最后一个规则。

我想我开始只是试图改变正则表达式,所以它不会匹配--(如a--b) -我认为它可能是一个消极的向前看,因为它断言,正则表达式不包含--(对吗?):

向前查找和向后查找,统称为"向后查找",是零长度断言,就像行开始和行结束,以及词锚的开始和结束一样。[…区别在于lookaround实际上匹配字符,但随后放弃匹配,只返回结果:匹配或不匹配。这就是为什么它们被称为"断言"。它们不使用字符串中的字符,而只断言是否可能匹配

但是将(?!--)添加到正则表达式(在regex101.com上)的不同位置,或者作为(?<!--)后面的查看,不会导致像a--b这样的字符串不匹配

。所有这些模式都匹配foo--bar,当它不应该。

(?!--)^[a-z][0-9_a-z-]*[0-9a-z]$
^(?!--)[a-z][0-9_a-z-]*[0-9a-z]$
^[a-z](?!--)[0-9_a-z-]*[0-9a-z]$
^[a-z](?!--)(?:[0-9_a-z-]*)[0-9a-z]$
^[a-z][0-9_a-z-]*(?!--)[0-9a-z]$
^[a-z][0-9_a-z-]*(?<!--)[0-9a-z]$

可以将负向前看放在匹配字符串开头的a-z之后。

因为你不想匹配-和-的任何组合,你可以使用2个字符类(?!.*[_-][_-])

由于[_-][_-]部分可以出现在字符串中的任何位置,因此您可以在它前面加上.*,可选地匹配任何字符。

如果省略.*,则断言仅在当前位置上运行,在本例中,在匹配字符串开头的a-z之后。

^[a-z](?!.*[_-][_-])[0-9_a-z-]*[0-9a-z]$

最新更新