这似乎符合我定义的规则,但我今晚才开始学习正则表达式,所以我想知道它是否正确。
规则:
正则表达式:
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
答案 0 :(得分:70)
问题中的规格不是很清楚,所以我只假设字符串只能包含ASCII字母和数字,连字符,下划线和空格作为内部分隔符。问题的关键在于确保第一个和最后一个字符不是分隔符,并且连续的行中永远不会有多个分隔符(无论如何,该部分看起来都很清楚)。这是最简单的方法:
/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/
匹配一个或多个字母数字字符后, if 有一个分隔符,必须后跟一个或多个字母数字字符;根据需要重复。
让我们从其他一些答案中看看正则表达式。
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
这实际上是相同的(假设您的正则表达式支持POSIX字符类表示法),但为什么使分隔符可选?你首先进入正则表达式的那一部分的唯一原因是,如果有一个分隔符或其他一些无效的字符。
/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
另一方面,这仅适用于,因为分隔符是可选的。在第一个分隔符之后,它一次只能匹配一个字母数字。为了匹配更多,它必须不断重复整个组:零分隔符后跟一个字母数字,一遍又一遍。如果第二个[a-zA-Z0-9]
后跟加号,它可以通过更直接的路线找到匹配。
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
这使用无限制的lookbehind,这是一个非常罕见的功能,但你可以使用前瞻来达到同样的效果:
/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/
这基本上对两个连续的分隔符执行单独的搜索,如果找到匹配则失败。然后主体只需要确保所有字符都是字母数字或分隔符,第一个和最后一个是字母数字。由于这两个是必需的,因此名称必须至少为两个字符。
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
这是你自己的正则表达式,它要求字符串以两个字母数字字符开头和结尾,如果字符串中有两个分隔符,则它们之间必须有两个字母数字。因此ab
,ab-cd
和ab-cd-ef
会匹配,但a
,a-b
和a-b-c
不会匹配。
此外,正如一些评论者指出的那样,正则表达式中的(_|-| )
应为[-_ ]
。那部分不是不正确的,但是如果你可以选择交替和字符类,你应该总是选择字符类:它们更高效,更可读。
同样,我并不担心“字母数字”是否应该包含非ASCII字符,或“空间”的确切含义,而是如何使用正则表达式强制实施非连续内部分隔符的策略。 / p>
答案 1 :(得分:21)
您可以将正则表达式简化为:
/^[a-zA-Z0-9]+([_ -]?[a-zA-Z0-9])*$/
使用Regexper显示:
如您所见,用户名始终必须以字母数字字符开头。特殊字符(_
,,
-
)必须后跟字母数字字符。最后一个字符必须是字母数字字符。
答案 2 :(得分:4)
([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*
是0或更多重复的alphanum,dashspace,alphanum。
所以它会匹配
a_aa_aa_a
但不是
aaaaa
完整的正则表达式无法匹配
a_aaaaaaaaa_a for example.
让我们回顾一下你想要的东西:
* Usernames can consist of lowercase and capitals or alphanumerica characters
* Usernames can consist of alphanumeric characters
* Usernames can consist of underscore and hyphens and spaces
* Cannot be two underscores, two hypens or two spaces in a row
* Cannot have a underscore, hypen or space at the start or end
开始很简单......只需匹配一个alphanum,然后(在行规则中加入两个)a(alphanum或dashspace)*并再次和alphanum。
要防止连续两个虚线空间,您可能需要了解前瞻/后视。
哦,关于其他答案:请下载Espresso,它真的可以帮助你解决这些问题。
答案 3 :(得分:3)
我建议写一些单元测试来让Regex通过它的步伐。从现在开始,当您发现Regex出现问题并需要更新时,这也会有所帮助。
答案 4 :(得分:2)
字母数字不仅仅是[a-zA-Z0-9]
,还有重音符号,西里尔语,希腊语和其他字母,可以在用户名中使用。
(_|-| )
可以替换为[-_ ]
字符类
答案 5 :(得分:1)
将POSIX字符类用于字母数字字符,使其适用于重音和其他外国字母字符:
/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/
更高效(防止捕获):
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
这些也可以防止组合使用多个空格/连字符/下划线的序列。 它不符合您的规范是否可取,而是您自己的正则表达式 似乎表明这就是你想要的。
答案 6 :(得分:0)
此处Expresso 3.0的另一个建议 - 非常容易使用和构建字符串。
答案 7 :(得分:0)
你的正则表达式不起作用。困难的部分是检查连续的空格/连字符。你可以使用这个,使用look-behind:
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
答案 8 :(得分:0)
从外观上看,该规则与“a_bc”,“ab_c”,“a_b”或“a_b_c”不匹配。
尝试:/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
它匹配上述情况,但没有任何空格,破折号或下划线彼此相邻的组合。例如:不允许使用“_-”或“_”。
答案 9 :(得分:0)