how to use regex to extract match string in scala?

Viewed 206

The string is given as

var filedate = parser("test_pb_PP_Quality_2-Report_20200707.csv");

The Parser function to extract "20200707" as below.

def parser(filename: String):String = {
    val extractDate = """(\d{8}).*""".r
    val extractDate(dd) = filename;
    dd;
}

But its return error as Exception in thread "main" scala.MatchError:

3 Answers

By default, a Regex created with the .r method is anchored, which means it must match the whole string. (think of your regex as being enclosed in ^ and $ )

You could use an unanchored regex instead:

def parser(filename: String):String = {
  val extractDate = """(\d{8})""".r.unanchored
  val extractDate(dd) = filename
  dd
}

This works, but is bad practice since "parsing" would throw an exception if your input does not match. More idiomatic would be to return an Option[String] and handle that at the calling site. For example:

def parser(filename: String): Option[String] = {
  """\d{8}""".r.findFirstIn(filename)
}

parser("test_pb_PP_Quality_2-Report_20200707.csv") match {
  case Some(datetime) => // do something
  case None           => // handle this case
}

You could try using Java's String#replaceAll here:

def parser(filename: String):String = {
    val extractDate = filename.replaceAll(".*(\\d{8}).*", "$1");
    extractDate;
}

println(parser("test_pb_PP_Quality_2-Report_20200707.csv"))

This prints:

20200707

Just allow some text before the numbers by adding .* to the beginning of the regular expression:

def parser(filename: String):String = {
    val extractDate = """.*(\d{8}).*""".r
    val extractDate(dd) = filename;
    dd;
}

You could also use a match-expression to handle the case where the filename does not have the expected format:

def parser(filename: String):String = {
    val extractDate = """.*(\d{8}).*""".r
    filename match {
      case extractDate(dd) => dd
      case _ => throw new RuntimeException(s"Invalid filename $filename")
    }
}
Related