我是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
为什么不在第二种情况下“测试”匹配?
答案 0 :(得分:9)
拿你的正则表达式:
"([^"]*)"(.*$)
使用.r
进行编译时,此字符串会生成一个regex
对象 - 如果它与输入字符串匹配,则必须产生 2 捕获的字符串 - 一个用于{{ 1}}和([^"]*)
的另一个。你的代码
(.*$)
应该反映这一点,所以也许你想要
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
方法返回 2 字符串列表,因为这是正则表达式说它抓住了。这很不幸,但编译器在这里无法帮助你,因为正则表达式是在运行时从字符串编译的。
一种替代方案是使用非捕获组:
unapplySeq
然后你的代码就可以了,因为 val stringRegex = """"([^"]*)"(?:.*$)"""
// ^^
现在将成为一个提取器对象
regex
方法仅返回一个捕获的组:
unapplySeq
查看Extractor Objects上的教程,以便更好地理解
tidyTokens foreach {
case regex(token) => println (token + " matches!")
case t => println ("No match for token " + t)
}
/ apply
/ unapply
如何运作。