2013-02-27 201 views
7

我是scala的新手。我想匹配双引号分隔字符串,我有点受以下行为不解:Scala正则表达式(用双引号分隔的字符串)

如果我做了以下内容:

val stringRegex = """"([^"]*)"(.*$)""" 
val regex = stringRegex.r 
val tidyTokens = Array[String]("1", "\"test\"", "'c'", "-23.3") 
tidyTokens.foreach { 
    token => if (token.matches (stringRegex)) println (token + " matches!") 
} 

我得到

"test" matches! 

否则如果我做到以下几点:

tidyTokens.foreach { 
    token => token match { 
     case regex(token) => println (token + " matches!") 
     case _ => println ("No match for token " + token) 
    } 
} 

我得到

No match for token 1 
No match for token "test" 
No match for token 'c' 
No match for token -23.3 

为什么在第二种情况下“测试”不匹配?

回答

9

把你的正则表达式:

"([^"]*)"(.*$) 

.r编译,这个字符串产生一个regex对象 - 它,如果它匹配它的输入字符串,必须得到抓获串 - 一个用于([^"]*)和另一个为(.*$)。您的代码

case regex(token) => ... 

应然反映此事,所以也许你想

case regex(token, otherStuff) => ... 

或者只是

case regex(token, _) => ... 

为什么?因为case regex(matchedCaputures...)语法有效,因为regex是 对象,并且有unapplySeq方法。 case regex(token) => ...翻译(大约)至:

case List(token) => ... 

哪里List(token)是什么regex.unapplySeq(inputString)回报:

regex.unapplySeq("\"test\"") // Returns Some(List("test", "")) 

你的正则表达式不匹配字符串"test"case声明正则表达式提取的unapplySeq方法返回的列表2字符串,因为这是正则表达式所捕获的。这很不幸,但编译器无法帮助您,因为正则表达式是在运行时从字符串编译的。

一种替代方法是使用非捕获组:

val stringRegex = """"([^"]*)"(?:.*$)""" 
//        ^^ 

那么你的代码将工作,因为regex现在是提取对象,其 unapplySeq方法返回只有一个捕获组:

tidyTokens foreach { 
    case regex(token) => println (token + " matches!") 
    case t => println ("No match for token " + t) 
} 

对 如何apply/unapply/看看上Extractor Objects教程,以便更好地理解作品。

+0

谢谢!也可以参考提取器对象! – gbgnv 2013-02-27 18:44:59

相关问题