Ruby on rails 如何使用正则表达式检查用户名格式
我需要使用正则表达式检查用户名格式。 我的用户名标准是:Ruby on rails 如何使用正则表达式检查用户名格式,ruby-on-rails,ruby,regex,Ruby On Rails,Ruby,Regex,我需要使用正则表达式检查用户名格式。 我的用户名标准是: 必须包含1个或多个字母,任意位置 可以在任何地方包含任意数量的数字 可以在任何位置包含最多2个或u3 ^[0-9\-\\*[a-z | a-z]+[0-9\-\\*$是我使用的,但这将拒绝使用诸如123hi123hi或hi123hi之类的用户名。我需要一些不依赖于字符串位置的东西 我使用RubyonRails来匹配字符串 Rails的一个非常低效的Ruby函数版本是: validate :check_username def chec
- 必须包含1个或多个字母,任意位置
- 可以在任何地方包含任意数量的数字
- 可以在任何位置包含最多2个或u3
^[0-9\-\\*[a-z | a-z]+[0-9\-\\*$
是我使用的,但这将拒绝使用诸如123hi123hi
或hi123hi
之类的用户名。我需要一些不依赖于字符串位置的东西
我使用RubyonRails来匹配字符串
Rails的一个非常低效的Ruby函数版本是:
validate :check_username
def check_username
if self.username.count("-") > 2
errors.add(:username, "cannot contain more than 2 dashes")
elsif self.username.count("_") > 2
errors.add(:username, "cannot contain more than 2 underscores")
elsif self.username.count("a-zA-Z") < 1
errors.add(:username, "must contain a letter")
elsif (self.username =~ /^[0-9a-zA-Z\-_]+$/) !=0
errors.add(:username, "cannot contain special characters")
end
end
验证:检查\u用户名
def check_用户名
如果self.username.count(“-”)大于2
错误。添加(:用户名,“不能包含超过2个破折号”)
elsif self.username.count(“”)>2
错误。添加(:用户名,“不能包含超过2个下划线”)
elsif self.username.count(“a-zA-Z”)<1
错误。添加(:用户名,“必须包含字母”)
elsif(self.username=~/^[0-9a-zA-Z\-\-\\\+$/)=0
错误。添加(:用户名,“不能包含特殊字符”)
结束
结束
这是您的正则表达式的改进版本
^[\w-]*[A-Za-z]+[\w-]*$
但这将无法计算出有多少个或uu,因此您需要另一个正则表达式来过滤或在代码中手动计算。
这是用于检查的正则表达式,不考虑其位置,仅限两个或两个以下[-\]:
^[A-Za-z\d]*[-_]{0,1}[A-Za-z\d]*[-_]{0,1}[A-Za-z\d]*$
如果只允许字母、数字、破折号和下划线 其他一切都被认为是一种特殊的性格 我认为这只是你的模式需要否定 而不是
(self.username=~/^[0-9a-zA-Z\-\-\\+$/)=0
请尝试(self.username=~/^[^0-9a-zA-Z\-\\+$/)=0
或者(self.username=~/^[\W-]+$/)>0
另外,为什么不对特殊字符进行计数,就像上面的条件一样?这里有两种方法可以使用 构造单个正则表达式
def username_valid?(username)
cnt = username.each_char.with_object(Hash.new(0)) do |c,cnt|
case c
when /\d/
when /[[:alpha:]]/
cnt[:letter] += 1
when '-'
cnt[:hyphen] += 1
when '_'
cnt[:underscore] += 1
else
return false
end
end
cnt.fetch(:letter, 0) > 0 && cnt.fetch(:hyphen, 0) <= 2 &&
cnt.fetch(:underscore, 0) <= 2
end
username_valid? "Bob" #=> true
username_valid? "Bob1_23_-" #=> true
username_valid? "z" #=> true
username_valid? "123--_" #=> false (no letters)
username_valid? "Melba1-23--_" #=> false (3 hyphens)
username_valid? "Bob1_23_-$" #=> false ($ not permitted)
由于正则表达式与字符串中字符的顺序有关,因此必须为以下每个组合构造一个正则表达式,然后将这些正则表达式“或”转换为单个正则表达式
- 一个字母,零连字符,零下划线
- 一个字母,零连字符,一个下划线
- 一个字母,零连字符,两个下划线
- 一个字母,一个连字符,零下划线
- 一个字母,一个连字符,一个下划线
- 一个字母,一个连字符,两个下划线
- 一个字母,两个连字符,零下划线
- 一个字母,两个连字符,一个下划线
- 一个字母,两个连字符,两个下划线
t0
,t1
,…,t8
。所需的单个整体正则表达式为:
/#{t0}|#{t1}|...|#{t8}/
让我们考虑<代码> T4(一个字母,一个连字符,一个下划线)的构造。 这种组合有六种可能的订单
- 字母、连字符、下划线
- 字母、下划线、连字符
- 连字符、字母、下划线
- 连字符、下划线、字母
- 下划线、字母、连字符
- 下划线、连字符、字母
r0
,r1
,…,r5
),然后“或”它们以获得t4
:
t4 = /#{r0}|#{r1}|#{r2}|#{r3}|#{r4}|#{r5}/
现在我们考虑构造一个正则表达式>代码> R0,它将实现这些排序中的第一个(一个字母,一个连字符,一个下划线):
其他五个ri
的构造都类似
然后,我们需要计算除第五个组合之外的八个组合中的每个组合的ti
<代码>t0(一个字母,零连字符,零下划线)很简单:
相比之下,t8
(一个字母、两个连字符、两个下划线)的正则表达式要比t4
(如上所述)长得多,因为必须为5中的每一个手工创建正则表达式/(2!*2!)#=>30个订单(r0
,r1
,…,r29
)
现在很明显,使用单个正则表达式并不是验证用户名的正确工具
不要构造单个正则表达式
def username_valid?(username)
cnt = username.each_char.with_object(Hash.new(0)) do |c,cnt|
case c
when /\d/
when /[[:alpha:]]/
cnt[:letter] += 1
when '-'
cnt[:hyphen] += 1
when '_'
cnt[:underscore] += 1
else
return false
end
end
cnt.fetch(:letter, 0) > 0 && cnt.fetch(:hyphen, 0) <= 2 &&
cnt.fetch(:underscore, 0) <= 2
end
username_valid? "Bob" #=> true
username_valid? "Bob1_23_-" #=> true
username_valid? "z" #=> true
username_valid? "123--_" #=> false (no letters)
username_valid? "Melba1-23--_" #=> false (3 hyphens)
username_valid? "Bob1_23_-$" #=> false ($ not permitted)
该方法可以改为在确定正则表达式不正确时立即写入以返回false
def username_valid?(username)
cnt = username.each_char.with_object(Hash.new(0)) do |c,cnt|
case c
when /\d/
when /[[:alpha:]]/
cnt[:letter] += 1
when '-'
return false if cnt[:hyphen] == 2
cnt[:hyphen] += 1
when '_'
return false if cnt[:underscore] == 2
cnt[:underscore] += 1
else
return false
end
end
cnt.fetch(:letter, 0) > 0
end
对于正则表达式来说,这是一个不好的用法,因为您的数据结构不够。相反,一系列简单的测试将告诉您需要了解的内容:
def valid?(str)
str[/[a-z]/i] && str.tr('^-_', '').size <= 2
end
%w(123hi123hi hi123hi).each do |username|
username # => "123hi123hi", "hi123hi"
valid?(username) # => true, true
end
所以相反
def valid?(str)
str.downcase.tr('^a-z', '').size >= 0 && str.tr('^-_', '').size <= 2
end
规则
可以在任何地方包含任意数量的数字
不值得测试,所以我忽略了它。^
在Ruby中表示行的开头,而不是字符串;您几乎总是想使用\A
来代替。类似地,\z
而不是$
。但是使用^
和$
可以允许用户名通过包含换行符的字符串,这就是为什么需要使用字符串锚(\A
和\z
)而不是行锚(^
和$
)。您是说^\w*$
与任何单词的两行匹配吗?OP的check_username
方法显示用户名可能包含,例如,两个连字符和一个下划线。你的正则表达式不允许这样。它也没有强制要求它必须至少包含一个字母。请注意,[-\]{0,1}
与[-\]{,1}
或更简单的是,[-\]?
相同。我听到的是他说计数(连字符或下划线)^
在Ruby中表示行的开头,而不是字符串;您几乎总是想使用\A
来代替。类似地,括号内的\z
而不是$
^
是对这些括号内其余表达式的否定。
def valid?(str)
str[/[a-z]/i] && str.tr('^-_', '').size <= 2
end
%w(123hi123hi hi123hi).each do |username|
username # => "123hi123hi", "hi123hi"
valid?(username) # => true, true
end
/[a-z]/i
def valid?(str)
str.downcase.tr('^a-z', '').size >= 0 && str.tr('^-_', '').size <= 2
end
'123hi123hi'.downcase # => "123hi123hi"
.tr('^a-z', '') # => "hihi"
.size # => 4
'hi123hi'.downcase # => "hi123hi"
.tr('^a-z', '') # => "hihi"
.size # => 4
'hi-123_hi'.downcase # => "hi-123_hi"
.tr('^a-z', '') # => "hihi"
.size # => 4