Ruby Regex验证格式xxx - ####

时间:2012-08-29 19:55:41

标签: ruby-on-rails ruby ruby-on-rails-3

我需要在我的模型中按照以下格式验证输入证据编号。

XXX-### 
XXX-#### 
XXX-##### 
XXX-######
XXXX-#####

XXXX是字母,####是数字

我的模型代码中有以下内容。

validates_format_of :evidence_number, :with=> /[A-Z a-z]{3}-\d{3,6}/

它仅适用于小于3的数字,即它适用于XXX-12但不适用于超过6的数字,即它不适用于XXX-1234567

4 个答案:

答案 0 :(得分:3)

你应该使用\A(字符串的开头)和\z(字符串的结尾)锚,而不是^(行的开头)和$(结束) ():

validates_format_of :evidence_number, :with=> /\A[A-Z a-z]{3}-\d{3,6}\z/

一个简单的例子将说明不同之处:

>> "wrong\nXXX-999\nanchors" =~ /^[A-Z a-z]{3}-\d{3,6}$/
=> 6
>> "wrong\nXXX-999\nanchors" =~ /\A[A-Z a-z]{3}-\d{3,6}\z/
=> nil
>> "XXX-999" =~ /^[A-Z a-z]{3}-\d{3,6}$/
=> 0
>> "XXX-999" =~ /\A[A-Z a-z]{3}-\d{3,6}\z/
=> 0

您几乎总是希望在Ruby中使用\A\z代替^$

如果在连字符后需要“至少三位数”,则需要:

/\A[A-z a-z]{3}-\d{3,}\z/

并且Kenny Grant是正确的,字符类中的空格看起来很奇怪。

答案 1 :(得分:1)

尝试添加^开头和$结尾。

validates_format_of :evidence_number, :with=> /^[A-Za-z]{3,4}-\d{3,6}$/

尽管使用mu is too short的答案。

答案 2 :(得分:1)

您可能最好设置一些测试代码,并单独测试正则表达式(或理想情况下设置单元测试并以此方式进行测试)。

invalid   = %w[777-2345 ABCD-12 ABCD-12345678 AB-12345678 ABC-1234567]
valid     = %w[ABC-12345 ABCD-123 ABCD-1234 ABCD-12345 ABCD-123456]

def validate codes,regex
  codes.each do |code|
  if code =~ regex
     puts "Valid code #{code}" 
   else
     puts "Invalid code #{code}"
   end
 end
end

使用正则表达式测试上述内容时,会出现一些问题。根据您的描述,我不明白为什么您的正则表达式将空格包含为允许的字符 - 对于代码,这似乎不太可能是有效的代码。所以你可能会用这样的东西做得更好:

/\A[A-Za-z]{3,4}-\d{3,6}\z/

将匹配限制为完整字符串,并将第一个匹配限制为3或4个字母字符,最终匹配限制为3-6个数字。这假设####在您的示例中不是错误的:

puts "\n\nUSING NEW REGEX"
puts "Validating valid codes"
validate valid,/\A[A-Za-z]{3,4}-\d{3,6}\z/
puts "\nValidating INVALID codes"
validate invalid,/\A[A-Za-z]{3,4}-\d{3,6}\z/

答案 3 :(得分:0)

添加字符串开头和结尾的正则表达式字符:

validates_format_of :evidence_number, :with=> /^[A-Z a-z]{3}-\d{3,6}$/

ruby-1.9.3-p125 :000 > "ABC-1234567".match /[A-Z a-z]{3}-\d{3,6}/
 => #<MatchData "ABC-123456"> 
ruby-1.9.3-p125 :001 > "ABC-1234567".match /^[A-Z a-z]{3}-\d{3,6}$/
 => nil 
相关问题