我需要帮助编写正则表达式以满足以下要求:
- 以一封信开头
- 以字母或数字结尾
- 只有字母、数字、下划线和连字符作为内部字符
以下表达式运行良好,但它允许下划线作为最后一个字符。它应该只允许最后一个字符使用字母或数字:
^[A-Za-z][\w-]*\w$
执行您要求的方法之一是使用负前瞻约束:
^[A-Za-z][\w-]*(?!_)\w$
另一种方法是写出你想要的字符类(Tcl定义\w
为[[:alnum:]_]
,即alnum
类加下划线):
^[A-Za-z][\w-]*[[:alnum:]]$
这些接受完全相同的字符串。哪个更好?好吧,唯一可以确定的真正方法是测试(这些时间是在我的旧笔记本电脑上使用较旧的 Tcl 版本;查看相对时间,而不是绝对时间):
% set a "abc123abc123abc123_123"
abc123abc123abc123_123
% set b "abc123abc123abc123123_"
abc123abc123abc123123_
% regexp {^[A-Za-z][\w-]*(?!_)\w$} $a
1
% regexp {^[A-Za-z][\w-]*(?!_)\w$} $b
0
% time {regexp {^[A-Za-z][\w-]*(?!_)\w$} $a} 1000
21.207069999999998 microseconds per iteration
% time {regexp {^[A-Za-z][\w-]*(?!_)\w$} $b} 1000
20.577612000000002 microseconds per iteration
% regexp {^[A-Za-z][\w-]*[[:alnum:]]$} $a
1
% regexp {^[A-Za-z][\w-]*[[:alnum:]]$} $b
0
% time {regexp {^[A-Za-z][\w-]*[[:alnum:]]$} $a} 1000
4.0455700000000006 microseconds per iteration
% time {regexp {^[A-Za-z][\w-]*[[:alnum:]]$} $b} 1000
3.510597 microseconds per iteration
这对我来说看起来很有结论:当你可以编写你真正想要的类时,不要使用前瞻约束。(看起来RE引擎也有未来优化的潜力......)
您应该使用^[a-zA-Z][-\w]*[a-zA-Z\d]$
或^[a-zA-Z][-\w]*[^\W_]$
^[a-z][a-z0-9_\-]+[a-z0-9]$(?i)