我的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]$