Java 为什么scala.util.matching.Regex';显然';Scala提取器失败?

Java 为什么scala.util.matching.Regex';显然';Scala提取器失败?,java,regex,scala,pattern-matching,data-extraction,Java,Regex,Scala,Pattern Matching,Data Extraction,我使用Scala提取器(即:模式匹配中的Regex inside)来识别double和long,如下所示 我的问题是:为什么在模式匹配中使用Regex时显然失败了,而在if/then/else表达式链中使用Regex时却能清楚地提供预期的结果 val LONG=“”^(0 |-?[1-9][0-9]*)$” val DOUBLE=“[0-9]*)([1-9][0-9]*。[0-9]*)([0-9]+)([Ee][+-]?[0-9]+)([Ee][+-]?[0-9]+)?$” val scalon

我使用Scala提取器(即:模式匹配中的Regex inside)来识别double和long,如下所示

我的问题是:为什么在模式匹配中使用Regex时显然失败了,而在if/then/else表达式链中使用Regex时却能清楚地提供预期的结果

val LONG=“”^(0 |-?[1-9][0-9]*)$”
val DOUBLE=“[0-9]*)([1-9][0-9]*。[0-9]*)([0-9]+)([Ee][+-]?[0-9]+)([Ee][+-]?[0-9]+)?$”
val scalong:scala.util.matching.Regex=LONG.r
val scalaDOUBLE:scala.util.matching.Regex=DOUBLE.r
val types1=序列(“abc”、“3”、“3.0”、“3.0E-05”、“NaN”)。地图(文本=>
文本匹配{
大小写缩放(长)=>s“长”
大小写缩放双精度(双精度)=>s“双精度”
大小写=>s“字符串”
})
//结果类型1:Seq[String]=列表(“String”、“Long”、“String”、“String”、“String”)
val types2=序列(“abc”、“3”、“3.0”、“3.0E-05”、“NaN”)。地图(文本=>
if(scalaDOUBLE.findFirstIn(text).isDefined)“Double”else
if(scalong.findFirstIn(text).isDefined)“Long”else
“字符串”)
//结果类型2:Seq[String]=列表(“String”、“Long”、“Double”、“Double”、“Double”)
从上面可以看出,
types2
提供了预期的结果,而
types1
在预期为“Double”时告诉“String”,显然指出了正则表达式处理中的失败

编辑:在@alex savitsky和@leo-c的帮助下,我完成了如下所示的工作,效果如预期。但是,我必须记住在模式匹配中提供一个空参数列表,否则它会给出错误的结果。这在我看来很容易出错

val LONG=“”^(?:0 |-?[1-9][0-9]*)$”
val DOUBLE=“^NaN |-?(?:[0-9]*)?(?:[1-9][0-9]*.[0-9]*)(?:\[0-9]+)(?:[Ee][+-][[0-9]+)?$”
val scalong:scala.util.matching.Regex=LONG.r
val scalaDOUBLE:scala.util.matching.Regex=DOUBLE.r
val types1=序列(“abc”、“3”、“3.0”、“3.0E-05”、“NaN”)。地图(文本=>
文本匹配{
大小写缩放()=>s“长”
大小写scalaDOUBLE()=>s“Double”
大小写=>s“字符串”
})
//结果类型1:Seq[String]=列表(“String”、“Long”、“Double”、“Double”、“Double”)
val types2=序列(“abc”、“3”、“3.0”、“3.0E-05”、“NaN”)。地图(文本=>
if(scalaDOUBLE.findFirstIn(text).isDefined)“Double”else
if(scalong.findFirstIn(text).isDefined)“Long”else
“字符串”)
//结果类型2:Seq[String]=列表(“String”、“Long”、“Double”、“Double”、“Double”)

编辑:确定。。。尽管容易出错。。。它是一个提取器模式,在后台使用
不应用
,在这种情况下,我们必须将参数传递给
不应用
@alex savitsky在他的编辑中使用了
.*
,这明确了删除所有捕获组的意图。看起来不错。

match
匹配整个输入,而
findFirstIn
可以匹配部分输入内容,有时会导致更多匹配。事实上,
findFirstIn
将完全忽略边界标记

如果您打算匹配整个输入,请将您的
^
放在正则表达式的开头,如
val DOUBLE=“^NaN”?(0(\.[0-9]*)?([1-9][0-9]*\.[0-9]*)(\.[0-9]+)([Ee][+-][0-9]+)?$”
,则
类型1
将正确匹配这些类型

编辑:这是我对你的问题的测试用例

object Test extends App {
    val regex = """^NaN|-?(?:0(?:\.[0-9]*)?|(?:[1-9][0-9]*\.[0-9]*)|(?:\.[0-9]+))(?:[Ee][+-]?[0-9]+)?$""".r
    println(Seq("abc", "3", "3.0", "-3.0E-05", "NaN").map {
        case regex() => "Double"
        case _ => "String"
    })
}
结果在
列表中(字符串、字符串、双精度、双精度、双精度)

正如您所看到的,非捕获组起着至关重要的作用

如果仍要使用捕获组,可以使用
\u*
忽略捕获结果:

object Test extends App {
    val regex = """^NaN|-?(0(\.[0-9]*)?|([1-9][0-9]*\.[0-9]*)|(\.[0-9]+))([Ee][+-]?[0-9]+)?$""".r
    println(Seq("abc", "3", "3.0", "-3.0E-05", "NaN").map {
        case regex(_*) => "Double"
        case _ => "String"
    })
}

由于您在ScalaDuble中定义了多个捕获组,因此需要在相应的匹配案例中提供匹配数量的参数,如下所示:

val types1 = Seq("abc", "3", "3.0", "-3.0E-05", "NaN").map(text =>
  text match {
    case scalaLONG(long)                 => s"Long"
    case scalaDOUBLE(d1, d2, d3, d4, d5) => s"Double"
    case _                               => s"String"
  })
// types1: Seq[String] = List(String, Long, Double, Double, Double)
您可以检查捕获的组,如下所示:

"-3.0E-05" match { case scalaDOUBLE(d1, d2, d3, d4, d5) => (d1, d2, d3, d4, d5) }
// res1: (String, String, String, String, String) = (3.0,null,3.0,null,E-05)

这些论点是没有必要的。如果省略,Scala仍将匹配输入,而不会填充groups@Alex萨维茨基,你是对的,
“-3.0E-05”匹配{case scalaDOUBLE=>“Double”}
也可以工作,除了在OP的原始match case语句中添加一个额外的
case
catch all会不必要地触发编译器警告。感谢@leo-c对讨论的贡献,提出了涉及捕获组参数的问题。:-)您说过“那么类型2将正确匹配类型”。但是
types2
已经是正确的结果。我想你弄糊涂了。你的回答帮助我做了更多的步骤,但我没有真正遵循你的思路和/或你所做的测试。@RichardGomes对,我的意思是
类型1
,让我编辑答案你测试过吗?我已经替换了你提供的正则表达式,但它仍然给出错误的结果。我也会尝试使用非捕获组。是的,区别在于我使用的是非捕获组。我认为这需要一个更加翔实的编辑