【问题标题】:Pattern matching extract String Scala模式匹配提取字符串Scala
【发布时间】:2017-09-24 22:58:05
【问题描述】:

我想提取与我定义的两个正则表达式模式之一匹配的字符串的一部分:

  //should match R0010, R0100,R0300 etc 
  val rPat="[R]{1}[0-9]{4}".r
  // should match P.25.01.21 , P.27.03.25 etc
  val pPat="[P]{1}[.]{1}[0-9]{2}[.]{1}[0-9]{2}[.]{1}[0-9]{2}".r 

当我现在将提取元素的方法定义为:

  val matcher= (s:String) => s match {case pPat(el)=> println(el) // print the P.25.01.25
                                        case rPat(el)=>println(el) // print R0100 
                                        case _ => println("no match")}

并测试它,例如:

  val pSt=" P.25.01.21 - Hello whats going on?"
  matcher(pSt)//prints "no match" but should print P.25.01.21
  val rSt= "R0010  test test 3,870" 
  matcher(rSt) //prints also "no match" but should print R0010
  //check if regex is wrong
  val pHead="P.25.01.21"
  pHead.matches(pPat.toString)//returns true
  val rHead="R0010"
  rHead.matches(rPat.toString)//return true

我不确定正则表达式是否错误,但匹配方法适用于元素。那么这种方法有什么问题呢?

【问题讨论】:

    标签: regex scala pattern-matching


    【解决方案1】:

    当您对字符串使用模式匹配时,您需要记住:

    • 您传递的.r 模式需要匹配整个字符串,否则将不返回任何匹配项(解决方案是使模式.r.unanchored
    • 一旦取消锚定,请注意不需要的匹配:R[0-9]{4} 将匹配 R1234 中的 CSR123456(解决方案根据您的实际要求而有所不同,通常单词边界 \b 就足够了,或者是否定的lookarounds可以使用)
    • match 块内,如果您想取回一些值,正则表达式匹配函数需要存在捕获组(您在pPat(el)rPat(el) 中将其定义为el

    所以,我建议following solution

    val rPat="""\b(R\d{4})\b""".r.unanchored
    val pPat="""\b(P\.\d{2}\.\d{2}\.\d{2})\b""".r.unanchored
    
    val matcher= (s:String) => s match {case pPat(el)=> println(el) // print the P.25.01.25
        case rPat(el)=>println(el) // print R0100 
        case _ => println("no match")
    }
    

    那么,

    val pSt=" P.25.01.21 - Hello whats going on?"
    matcher(pSt) // => P.25.01.21
    val pSt2_bad=" CP.2334565.01124.212 - Hello whats going on?"
    matcher(pSt2_bad) // => no match
    val rSt= "R0010  test test 3,870" 
    matcher(rSt) // => R0010
    val rSt2_bad = "CSR00105  test test 3,870" 
    matcher(rSt2_bad) // => no match
    

    关于模式的一些注释:

    • \b - 前导词边界
    • (R\d{4}) - 精确匹配 4 位数字的捕获组
    • \b - 词尾边界

    由于用于定义字符串文字的三引号,因此无需转义反斜杠。

    【讨论】:

      【解决方案2】:

      在你的模式中引入组:

      val rPat=".*([R]{1}[0-9]{4}).*".r
      
      val pPat=".*([P]{1}[.]{1}[0-9]{2}[.]{1}[0-9]{2}[.]{1}[0-9]{2}).*".r 
      
      ...
      
      scala> matcher(pSt)
      P.25.01.21
      
      scala> matcher(rSt)
      R0010
      

      【讨论】:

      • 感谢您完成了这项工作!
      【解决方案3】:

      如果按照以下方式编写代码,将生成所需的结果。后面的参考API文档是http://www.scala-lang.org/api/2.12.1/scala/util/matching/Regex.html

        //should match R0010, R0100,R0300 etc
        val rPat="[R]{1}[0-9]{4}".r
        // should match P.25.01.21 , P.27.03.25 etc
        val pPat="[P]{1}[.]{1}[0-9]{2}[.]{1}[0-9]{2}[.]{1}[0-9]{2}".r
      
      
        def main(args: Array[String]) {
          val pSt=" P.25.01.21 - Hello whats going on?"
          val pPatMatches = pPat.findAllIn(pSt);
          pPatMatches.foreach(println)
          val rSt= "R0010  test test 3,870"
          val rPatMatches = rPat.findAllIn(rSt);
          rPatMatches.foreach(println)
      
        }
      

      请告诉我这是否适合您。

      【讨论】:

        猜你喜欢
        • 2016-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-10
        • 1970-01-01
        • 2015-08-27
        • 1970-01-01
        相关资源
        最近更新 更多