Ruby on Rails中的这个正则表达式有什么问题?

时间:2012-01-07 04:04:17

标签: ruby-on-rails regex

我写了一个正则表达式来帮助验证游戏角色名称的字符串。它以某种方式传递看似无效的字符串,而不是传递看似有效的字符串。

要求:

  • 以大写字母开头
  • 之后有任意数量的字母数字字符(包括空格)

这是在字符模型中进行验证的rails代码:

validates :name, format: { with: %r{[A-Z][a-zA-Z0-9\s]*} }

这是我正在使用的单元测试

test "character name should be properly formatted and does not contain any special characters" do
    character = get_valid_character
    assert character.valid?

    character.name = "aBcd"
    assert character.invalid?, "#{character.name} should be invalid"

    character.name = "Number 1"
    assert character.valid?, "#{character.name} should be valid"

    character.name = "McDonalds"
    assert character.valid?, "#{character.name} should be valid"

    character.name = "Abcd."
    assert character.invalid?, "#{character.name} should be invalid"

    character.name = "Abcd%"
    assert character.invalid?, "#{character.name} should be invalid"
end

问题: 正则表达式不传递“aBcd”,“Abcd。”和“Abcd%”。现在,我知道这是有效的,因为我在Python中测试了它,它的工作方式与您期望的一样。

是什么给出了?

感谢您的帮助!

2 个答案:

答案 0 :(得分:6)

正则表达式在给定字符串中的任何位置查找匹配项,除非另有说明。

因此测试字符串'aBcd'无效,但它包含一个有效的子字符串:'Bcd'。与'Abcd%'相同,其中有效子字符串为'Abcd'

如果要匹配整个字符串,请将其用作正则表达式:

# \A matches string beginning, \z matches string end
%r{\A[A-Z][a-zA-Z0-9\s]*\z}

PS:有些人会说要将字符串的开头与^匹配,而将结尾与$匹配。在Ruby中,这些符号匹配的开头和结尾,而不是字符串。因此,如果您使用"ABCD\n%"^$仍会匹配,但如果您使用\A\z则不匹配。有关详情,请参阅Rails security guide

答案 1 :(得分:0)

如果您只想匹配字符串开头的大写字母,则需要输入“行首”标记^,如下所示:

validates :name, format: { with: %r{^[A-Z][a-zA-Z0-9\s]*} }

查看Rubular以使用正则表达式