Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using regex in Scala to group and pattern match

Tags:

regex

scala

I need to process phone numbers using regex and group them by (country code) (area code) (number). The input format:

country code: between 1-3 digits , area code: between 1-3 digits , number: between 4-10 digits

Examples:

1 877 2638277
91-011-23413627

And then I need to print out the groups like this:

CC=91,AC=011,Number=23413627

This is what I have so far:

String s = readLine
val pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r
val ret = pattern.findAllIn(s)
println("CC=" + ret.group(1) + "AC=" + ret.group(2) + "Number=" + ret.group(3));

The compiler said "empty iterator." I also tried:

val (cc,ac,n) = s

and that didn't work either. How to fix this?

like image 828
user3025403 Avatar asked Nov 23 '13 17:11

user3025403


1 Answers

The problem is with your pattern. I would recommend using some tool like RegexPal to test them. Put the pattern in the first text box and your provided examples in the second one. It will highlight the matched parts.

You added spaces between your groups and [ -] separators, and it was expecting spaces there. The correct pattern is:

val pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r

Also if you want to explicitly get groups then you want to get a Match returned. For an example the findFirstMatchIn function returns the first optional Match or the findAllMatchIn returns a list of matches:

val allMatches = pattern.findAllMatchIn(s)
allMatches.foreach { m =>
  println("CC=" + m.group(1) + "AC=" + m.group(2) + "Number=" + m.group(3))
}

val matched = pattern.findFirstMatchIn(s)
matched match {
  case Some(m) =>
    println("CC=" + m.group(1) + "AC=" + m.group(2) + "Number=" + m.group(3))
  case None =>
    println("There wasn't a match!")
}

I see you also tried extracting the string into variables. You have to use the Regex extractor in the following way:

val Pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r
val Pattern(cc, ac, n) = s
println(s"CC=${cc}AC=${ac}Number=$n")

And if you want to handle errors:

s match {
  case Pattern(cc, ac, n) =>
    println(s"CC=${cc}AC=${ac}Number=$n")
  case _ =>
    println("No match!")
}

Also you can also take a look at string interpolation to make your strings easier to understand: s"..."

like image 186
Akos Krivachy Avatar answered Sep 30 '22 06:09

Akos Krivachy