2
votes

I am new to scala. I am trying something on the regular expression pattern matching. I am following the example from here: https://alvinalexander.com/scala/how-to-extract-parts-strings-match-regular-expression-regex-scala

Given below is the code that I have written which works but is obviously not the best way.
Scenario: I have a regex pattern with me.

"([a-z0-9]+)_([0-9]+)_([v|V][0-9]+)_(\\d{4})(\\d{2})(\\d{2}).(xls|xlsx)".r

I have a string that defines what I am expecting for a given scenario.
val param = "manufacturer/order/version"

Question: I don't want to pass hardcoded values in case pattern(manufacturer, order, version) but get the output in the variables manufacturer, order and version? One way is defining all the variables initially, but that would mean changing the code every time i need to change a string. Is there a way to do it dynamically or a better way of using regex in scala.

package com.testing

class DynamicFolder() {

  def dynamicPath(fileName: String): Map[String, String] = { 
    println("File Name: " + fileName)

    val param = "manufacturer/order/version"

    var patternString = param.replaceAll("/", ", ")
    println(patternString)

    val pattern = "([a-z0-9]+)_([0-9]+)_([v|V][0-9]+)_(\\d{4})(\\d{2})(\\d{2}).(xls|xlsx)".r
    val paramMap: Map[String, String] = fileName match {
      case pattern(manufacturer, order, version) => {
        println(s"Manufacturer: $manufacturer, Order: $order, version: $version")
        Map("manufacturer" -> manufacturer, "order" -> order, "version" -> version)
      }

      case pattern(manufacturer, order, version, yyyy, mm, dd, format) => {
        println(s"Manufacturer: $manufacturer, Order: $order, version: $version")
        Map("manufacturer" -> manufacturer, "order" -> order, "version" -> version)
      }

      case _ => throw new IllegalArgumentException
    }  
    paramMap
  }
}

object hello {

  def main(args: Array[String]): Unit = {
    var dynamicFolder = new DynamicFolder

    val fileName = "man1_18356_v1_20180202.xls"
    val tgtParams = dynamicFolder.dynamicPath(fileName)
    var tgtPath = "" 
    for ((k, v) <- tgtParams) {
      printf("key: %s, value: %s\n", k, v)
      tgtPath = tgtPath + "/" + tgtParams(k)
    }

    println ("Target path: "+tgtPath)
  }
}


Output of the code:

File Name: man1_18356_v1_20180202.xls
manufacturer, version, order
Manufacturer: man1, Order: 18356, version: v1
key: manufacturer, value: man1
key: order, value: 18356
key: version, value: v1
Target path: /man1/18356/v1

Thanks!

1
Do you mean you want to capture all groups in a single Seq which you can then access using indexes?Dennis Hunziker
Hi Dennis, Yes more on that line. Thanks!Dwarrior
Ex. Instead of passing all values hardcoded, I want to get the values in run time <br />case pattern(manufacturer, order, version, yyyy, mm, dd, format)<br / > and store the values from the actual string against each of these values. Sometimes, I might need only 3 values which may not be in order, ex: I may need order, version and dd once the pattern matching is successful.Dwarrior
Are you just looking to replace the variables with something like: case pattern(groups@_*)? that would give you access to all values in a more dynamic way.Dennis Hunziker
Can you please provide me the snippet so that I can test? Thanks!Dwarrior

1 Answers

0
votes

This is how you can collect all groups and process them yourself:

val paramMap: Map[String, String] = fileName match {
    case pattern(groups@_*) if groups.nonEmpty => {
        // Access group with groups(0), groups(1) etc.
    }

    case _ => throw new IllegalArgumentException
}