如何编写匹配Ruby命名空间类/模块名的正则表达式?
嘿,这个问题我熟!你现在的正则只能匹配最多两段命名空间,想要支持任意层级的话,只需要给后面的::+单词部分加上重复量词就好啦。
基础解决方案(匹配字母数字组成的命名空间)
直接把你原来的正则里的非捕获组改成可重复零次或多次就行:
string.scan /[a-zA-Z0-9]+(?:\:\:[a-zA-Z0-9]+)*/
解释一下关键部分:
[a-zA-Z0-9]+:匹配第一个“单词”(至少一个字母/数字)(?:\:\:[a-zA-Z0-9]+)*:非捕获组里是::加一个单词,*表示这个组合可以出现0次或多次——这样既支持单个单词(比如MyClass),也支持两层(Foo::Bar)、三层(Foo::Bar::Baz)甚至更多层级的命名空间。
更贴合Ruby实际标识符的版本
如果你想严格匹配Ruby合法的类/模块名,要注意Ruby的标识符允许下划线,且首字符可以是字母或下划线(后面可以是字母、数字、下划线),所以正则可以调整成:
string.scan /[a-zA-Z_][a-zA-Z0-9_]*(?:\:\:[a-zA-Z_][a-zA-Z0-9_]*)*/
这个版本就能正确匹配像MyModule::my_private_class这类符合Ruby命名规范的标识符了。
精确匹配整个字符串(避免部分匹配)
如果你要确保整个字符串就是一个合法的命名空间(而不是从长文本里提取),可以加上行首^和行尾$锚点:
# 检查某个字符串是否是合法命名空间 if "Foo::Bar::Baz" =~ /^[a-zA-Z_][a-zA-Z0-9_]*(?:\:\:[a-zA-Z_][a-zA-Z0-9_]*)*/ puts "合法的命名空间!" end
举个实际例子,假设你有字符串:
text = "User Admin::UserGroup Order::Item::Variant"
用基础版正则扫描会得到:["User", "Admin::UserGroup", "Order::Item::Variant"]
完全符合你的需求~
内容的提问来源于stack exchange,提问作者coconup
相关产品推荐
相关产品推荐

