首页 > 解决方案 > 正则表达式来测试类名的标准

问题描述

我正在构建一个正则表达式来检查字符串是否符合 ruby​​ 类名称的标准,换句话说,它必须是驼峰式。第一个字符必须是大写字母,所有后续字符可以是小写字母或数字。这可以重复,例如 SomeRandomClass。

下面,我使用一个字符类来匹配单个字母。然后另一个字符类匹配任何字母或数字一次或多次。

'This' =~ /^([A-Z][a-z0-9]+)$/
 # => 0 

但是 Ruby 类可以只有一个大写字母而没有任何后续的小写字母或数字,因此我尝试使用 使第二个字符类可选?:,但它似乎不起作用:

'ThisIsATest' =~ /^([A-Z](?:[a-z0-9]+))+$/
 # => nil 

我究竟做错了什么?

标签: rubyregex

解决方案


我相信你想要以下。

r = /
    \A           # match the beginning of the string
    [A-Z]        # match an upper case English letter
    \p{Alnum}*   # match zero or more Unicode letters or digits
    \z           # match the end of the string
    /x           # free-spacing regex definition mode

'ThisIsATest'.match? r  #=> true
'TIsAT22Test'.match? r  #=> true
'thisIsATest'.match? r  #=> false
'ThisIsATest?'.match? r #=> false
'T'.match? r            #=> true
'LeMêmeTest'.match? r   #=> true
'Être'.match? r         #=> false
''.match? r             #=> false

只能测试第一个字符(必须是字母)的大小写,因为剩余字母的任何大小写组合都可以解释为对应于驼峰式名称。例如,'TIsAT22Test'.match? r #=> true因为它可以被视为'T Is A T22 Test'. 同样'TIsAT22test'.match? r #=> true,因为它可以被视为'T Is A T22test'

奇怪的是,虽然常量名称可能包含 Unicode 字母,但它们必须以 26 个英文字母之一开头A-Z。无论如何,这是通过 Ruby MRI 2.5.x 实现的。但是,Ruby MRI v2.6(将于 2018 年 12 月 25 日发布)中的变化之一是常量可以以大约 1,853 个额外字符开头(来源)。大概(我将调查和编辑以显示我的发现),任何s满足的字符都s.match? /\p{Upper}/ #=> true可以以常量名称开头,因此可以以模块名称开头。如果是这样,上面的正则表达式应该相应地改变。

1. 在 Ruby v2.5.1 中,可以看出这Même是一个有效的常量名称:Même = 4; Même = 5 #=> warning: already initialized constant。然而,Être不是。其实Être就是一个局部变量的名字:Être = 7; binding.local_variable_get(:Être) #=> 7.


推荐阅读