最近遇到一个需求需要使用正则表达式实现,内容如下:
1、可以包含字母、数字、下划线、破折号、点
2、不能以点开头或结尾
方案1(错解)
^[^.][A-Za-z0-9-_.]*[^.]$
(菜鸡本人提供)
发现此方案不能匹配单个英文字符,原因为前面的 [^.] 和 后面的 [^.] 都表示必须匹配一个非 . 的字符,导致单个字符根本不能符合要求;并且此方案遇到 #a 这样的 不以 . 开头的也会给通过,肯定是不行的
可视化图如下:

方案2(错解)
^[^.]([A-Za-z0-9-_.]*[^.])?$
(大佬1提供)
此方案使用第一个 [^.] 满足非 . 开头,后面的使用分组结合,满足可0次1匹配,很优秀
但是发现此方案还有不足,就是非 . 开头的字符都满足要求,这样显示是不行的,因为 #a 这样的也能符合要求
可视化图如下:

方案3(正解1)
^[A-Za-z0-9-_]+(\.+[A-Za-z0-9-_]+)*$
(大佬2提供)
此方案优秀,将需求整理为 ^a+(b+a+)*$ 的形式
以 (.+[A-Za-z0-9-_]+)* 这样组合的方式,尤其是中间的 .+ 完美适配 【不可以.结尾】这个规则
可视化图如下:

方案4(正解2)
^(?!\.)[A-Za-z0-9-_.](?<!\.)$
(大佬3)提供
此方案非常优秀,这位大佬的写法是 ^(?!.) 和 (?<!.)$ 这样的结合,将反前瞻与^ 结合,将 反后顾与 $ 结合,而不是与内容结合,应该是这样的思路
但是貌似很多场合这种写法都不支持,比如在Linux下,不知道php中是否支持,因为同时的前瞻+后顾,但是此思路是非常优秀的
方案5 (错解)
(菜鸡本人提供)
^(?<!\.)[A-Za-z0-9-_.]+(?!\.)$
本以为前瞻+后顾能解决,没想到总是不能满足不以 . 开头或结尾,方案4的写法为本写法的高级版本
除此以外,上面的匹配如果要加上中文,只需要 [\x{4e00}-\x{9fa5}A-Za-z0-9-_] 这样的形式即可,加上 \x{4e00}-\x{9fa5}
果然还是集体的力量强大,感谢 QQ群【专精正则表达式】 434252251 各位群友提供的优秀思路
原创文章,作者:witersen,如若转载,请注明出处:https://www.witersen.com