是否有可能将字符串拆分为lexems,如
"user@domain.com" match {
case name :: "@" :: domain :: "." :: zone => doSmth(name, domain, zone)
}
换言之,以与列表相同的方式......
答案 0 :(得分:20)
是的,您可以使用Scala的Regex功能执行此操作。
我找到了一个email regex on this site,如果这不适合你,可以随意使用另一个:
[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}
我们要做的第一件事是在组周围添加括号:
([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4})
有了这个,我们有三个小组:@
之前,@
和.
之间的部分,最后是TLD。
现在我们可以从中创建一个Scala正则表达式,然后使用Scala的pattern matching unapply将正则表达式中的组绑定到变量:
val Email = """([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4})""".r
Email: scala.util.matching.Regex = ([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z] {2,4})
"user@domain.com" match {
case Email(name, domain, zone) =>
println(name)
println(domain)
println(zone)
}
// user
// domain
// com
答案 1 :(得分:4)
一般来说,正则表达式非常低效,所以不建议。
您可以使用Scala模式匹配,通过调用字符串上的.toList将其转换为List [Char]。然后,您的部分name
,domain
和zone
也将是List [Char],将它们重新转换为字符串使用.mkString。虽然我不确定这是多么有效。
我已经使用基本的字符串操作(如substring,indexOf等)进行基准测试,用于各种用例与正则表达式相比,正则表达式通常慢一两个。当然,正则表达式是不可思议的。
更新:最好的办法是使用Parsers,原生Scala或Parboiled2
答案 2 :(得分:1)
从Scala 2.13
开始,可以按unapplying a string interpolator模式匹配String
s:
val s"$user@$domain.$zone" = "user@domain.com"
// user: String = "user"
// domain: String = "domain"
// zone: String = "com"
如果您期望输入格式错误,还可以使用match语句:
"user@domain.com" match {
case s"$user@$domain.$zone" => Some(user, domain, zone)
case _ => None
}
// Option[(String, String, String)] = Some(("user", "domain", "com"))