【问题标题】:Extract groups matched regex to array in scala将匹配正则表达式的组提取到scala中的数组
【发布时间】:2017-10-10 04:28:02
【问题描述】:

我遇到了这个问题。我有一个

val line:String = "PE018201804527901"

与此匹配的

regex : (.{2})(.{4})(.{9})(.{2})

我需要将每个组从正则表达式中提取到一个数组中。

结果是:

Array["PE", "0182","018045279","01"]

我尝试做这个正则表达式:

val regex =  """(.{2})(.{4})(.{9})(.{2})""".r
val x= regex.findAllIn(line).toArray

但它不起作用!

【问题讨论】:

    标签: arrays regex scala extract regex-group


    【解决方案1】:
    regex.findAllIn(line).subgroups.toArray
    

    【讨论】:

      【解决方案2】:

      请注意,findAllIn 不会自动锚定正则表达式模式,而是会在更长的字符串中找到匹配项。如果您只需要允许 17 个字符字符串内的匹配项,您可以使用 match 块,如下所示:

      val line = "PE018201804527901"
      val regex =  """(.{2})(.{4})(.{9})(.{2})""".r
      val results = line match {
        case regex(g1, g2, g3, g4) => Array(g1, g2, g3, g4)
        case _ => Array[String]()
      }
      // Demo printing
      results.foreach { m =>
        println(m)
      } 
      // PE
      // 0182
      // 018045279
      // 01
      

      查看Scala demo

      它还可以很好地处理初始化空字符串数组的不匹配场景。

      如果您需要获取所有匹配项和所有组,则需要将组抓取到列表中,然后将列表添加到列表缓冲区 (scala.collection.mutable.ListBuffer):

      val line = "PE018201804527901%E018201804527901"
      val regex =  """(.{2})(.{4})(.{9})(.{2})""".r
      val results = ListBuffer[List[String]]()
      
      val mi = regex.findAllIn(line)
      while (mi.hasNext) {
        val d = mi.next
        results += List(mi.group(1), mi.group(2), mi.group(3), mi.group(4))
      }
      // Demo printing
      results.foreach { m =>
        println("------")
        println(m)
        m.foreach { l => println(l) }
      }
      

      结果:

      ------
      List(PE, 0182, 018045279, 01)
      PE
      0182
      018045279
      01
      ------
      List(%E, 0182, 018045279, 01)
      %E
      0182
      018045279
      01
      

      this Scala demo

      【讨论】:

      • 没有比regex(g1, g2, g3, g4) => Array(g1, g2, g3, g4)更简洁的方式了吗?
      • @Narfanator 否,如果您想使用正则表达式模式匹配。
      【解决方案3】:

      @sheunis 你的解决方案很有帮助,最后我用这个方法解决了:

      def extractFromRegex (regex: Regex, line:String): Array[String] = {
         val list =  ListBuffer[String]()
         for(m <- regex.findAllIn(line).matchData;
            e <- m.subgroups)
         list+=e
      list.toArray
      

      }

      因为您的解决方案使用此代码:

      val line:String = """PE0182"""
      val regex ="""(.{2})(.{4})""".r  
      val t = regex.findAllIn(line).subgroups.toArray
      

      显示下一个异常:

      Exception in thread "main" java.lang.IllegalStateException: No match available
      at java.util.regex.Matcher.start(Matcher.java:372)
      at scala.util.matching.Regex$MatchIterator.start(Regex.scala:696)
      at scala.util.matching.Regex$MatchData$class.group(Regex.scala:549)
      at scala.util.matching.Regex$MatchIterator.group(Regex.scala:671)
      at scala.util.matching.Regex$MatchData$$anonfun$subgroups$1.apply(Regex.scala:553)
      at scala.util.matching.Regex$MatchData$$anonfun$subgroups$1.apply(Regex.scala:553)
      at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
      at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
      at scala.collection.immutable.List.foreach(List.scala:318)
      at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
      at scala.collection.AbstractTraversable.map(Traversable.scala:105)
      at scala.util.matching.Regex$MatchData$class.subgroups(Regex.scala:553)
      at scala.util.matching.Regex$MatchIterator.subgroups(Regex.scala:671)
      

      【讨论】:

      • 或更实用的语法:val list = regex.findAllIn(line).matchData.flatMap(_.subgroups)
      猜你喜欢
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-04
      • 2019-07-14
      • 2012-11-23
      • 2016-02-02
      • 2015-12-25
      相关资源
      最近更新 更多