如何在Scala中使用正则expression式进行模式匹配?

我希望能够find一个单词的第一个字母和一个组中的一个字母,如“ABC”之间的匹配。 在伪代码中,这可能看起来像这样:

case Process(word) => word.firstLetter match { case([ac][AC]) => case _ => } } 

但是,如何获取Scala中的第一个字母,而不是Java呢? 如何正确expression正则expression式? 是否有可能在一个案例课中做到这一点?

你可以这样做,因为正则expression式定义了提取器,但是你需要先定义正则expression式模式。 我没有访问Scala REPL来testing,但是这样的事情应该工作。

 val Pattern = "([a-cA-C])".r word.firstLetter match { case Pattern(c) => c bound to capture group here case _ => } 

从版本2.10开始,可以使用Scala的string插值function:

 implicit class Regex(sc: StringContext) { def r = new util.matching.Regex(sc.parts.mkString, sc.parts.tail.map(_ => "x"): _*) } scala> "123" match { case r"\d+" => true case _ => false } res34: Boolean = true 

更好的可以绑定正则expression式组:

 scala> "123" match { case r"(\d+)$d" => d.toInt case _ => 0 } res36: Int = 123 scala> "10+15" match { case r"(\d\d)${first}\+(\d\d)${second}" => first.toInt+second.toInt case _ => 0 } res38: Int = 25 

还可以设置更详细的绑定机制:

 scala> object Doubler { def unapply(s: String) = Some(s.toInt*2) } defined module Doubler scala> "10" match { case r"(\d\d)${Doubler(d)}" => d case _ => 0 } res40: Int = 20 scala> object isPositive { def unapply(s: String) = s.toInt >= 0 } defined module isPositive scala> "10" match { case r"(\d\d)${d @ isPositive()}" => d.toInt case _ => 0 } res56: Int = 10 

Dynamic types介绍中展示了一个令人印象深刻的示例:

 object T { class RegexpExtractor(params: List[String]) { def unapplySeq(str: String) = params.headOption flatMap (_.r unapplySeq str) } class StartsWithExtractor(params: List[String]) { def unapply(str: String) = params.headOption filter (str startsWith _) map (_ => str) } class MapExtractor(keys: List[String]) { def unapplySeq[T](map: Map[String, T]) = Some(keys.map(map get _)) } import scala.language.dynamics class ExtractorParams(params: List[String]) extends Dynamic { val Map = new MapExtractor(params) val StartsWith = new StartsWithExtractor(params) val Regexp = new RegexpExtractor(params) def selectDynamic(name: String) = new ExtractorParams(params :+ name) } object p extends ExtractorParams(Nil) Map("firstName" -> "John", "lastName" -> "Doe") match { case p.firstName.lastName.Map( Some(p.Jo.StartsWith(fn)), Some(p.`.*(\\w)$`.Regexp(lastChar))) => println(s"Match! $fn ...$lastChar") case _ => println("nope") } } 

正如delnan指出的那样,Scala中的match关键字与正则expression式无关。 要找出一个string是否与正则expression式匹配,可以使用String.matches方法。 要找出一个string是以大写还是小写开头,正则expression式应该是这样的:

 word.matches("[a-cA-C].*") 

你可以阅读这个正则expression式为“a,b,c,A,B或C后面跟着任何一个字符”( .表示“任何字符”, *表示“零次或多次”,所以“。*”是任意的串)。

在Andrew的回答中扩展一点:正则expression式定义提取器的事实可以用来很好地使用Scala的模式匹配来分解由正则expression式匹配的子串,例如:

 val Process = """([a-cA-C])([^\s]+)""".r // define first, rest is non-space for (p <- Process findAllIn "aha bah Cah dah") p match { case Process("b", _) => println("first: 'a', some rest") case Process(_, rest) => println("some first, rest: " + rest) // etc. } 

请注意,@ AndrewMyers的答案的方法将整个string匹配到正则expression式,并使用^$来锚定string两端的正则expression式。 例:

 scala> val MY_RE = "(foo|bar).*".r MY_RE: scala.util.matching.Regex = (foo|bar).* scala> val result = "foo123" match { case MY_RE(m) => m; case _ => "No match" } result: String = foo scala> val result = "baz123" match { case MY_RE(m) => m; case _ => "No match" } result: String = No match scala> val result = "abcfoo123" match { case MY_RE(m) => m; case _ => "No match" } result: String = No match 

最后没有.*

 scala> val MY_RE2 = "(foo|bar)".r MY_RE2: scala.util.matching.Regex = (foo|bar) scala> val result = "foo123" match { case MY_RE2(m) => m; case _ => "No match" } result: String = No match 

String.matches是在正则expression式中进行模式匹配的方法。

但是,作为一个方便的手段,真正的Scala代码中的word.firstLetter看起来像:

 word(0) 

Scala将Strings视为Char序列,所以如果出于某种原因想要显式获取String的第一个字符并匹配它,可以使用如下所示的内容:

 "Cat"(0).toString.matches("[a-cA-C]") res10: Boolean = true 

我不是build议这是做正则expression式模式匹配的一般方法,但它符合你提出的方法,首先find一个string的第一个字符,然后匹配正则expression式。

编辑:要清楚,我会这样做的方式,正如其他人所说:

 "Cat".matches("^[a-cA-C].*") res14: Boolean = true 

只是想显示一个尽可能接近你的初始伪代码的例子。 干杯!

首先我们应该知道正则expression式可以单独使用。 这里是一个例子:

 import scala.util.matching.Regex val pattern = "Scala".r // <=> val pattern = new Regex("Scala") val str = "Scala is very cool" val result = pattern findFirstIn str result match { case Some(v) => println(v) case _ => } // output: Scala 

其次,我们应该注意到,将正则expression式和模式匹配相结合将会非常强大。 这是一个简单的例子。

 val date = """(\d\d\d\d)-(\d\d)-(\d\d)""".r "2014-11-20" match { case date(year, month, day) => "hello" } // output: hello 

事实上,正则expression式本身已经非常强大, 我们唯一需要做的就是让Scala更强大。 以下是Scala文档中的更多示例: http : //www.scala-lang.org/files/archive/api/current/index.html#scala.util.matching.Regex