sscarduzio
sscarduzio

Reputation: 6188

Scala Regex within a pattern matching

I have a ADT representing the crypto algorithms I want to use/detect. The generic class Algo contains some utility methods, including a handy auto-generated regex useful to detect the name of the algo inside a string.

  sealed trait Algo {
    override def toString = this.getClass.getSimpleName.dropRight(1)
    val name = toString
    val javaName = toString.replaceFirst("HS", "HmacSHA")
    val r = s".*$name.*".r
    println(r)
  }
  case object HS256 extends Algo
  case object HS348 extends Algo
  case object HS512 extends Algo

  val someString = "__HS256__"
  val result = someString match {
          case HS256.r(_) => HS256
          case HS348.r(_) => HS348
          case HS512.r(_) => HS512
          case _ => throw new Exception("Algorithm can't be matched")
  }

The above prints (see the printlns in the trait constructor) the regexes how I expect them to look like, that is:

.*HS256.*
.*HS348.*
.*HS512.*

But none match and the program throws the exception instead of matching HS256. Why does this happen, since this apparently equivalent line works well:

"__HS256__".matches(".*HS256.*")

Upvotes: 1

Views: 77

Answers (1)

sepp2k
sepp2k

Reputation: 370435

The pattern r(p), where r is a regex and p is another pattern, matches a given string if that string matches the regex and the pattern p matches the first capturing group of the regex match. Since your regex does not have any capturing groups, no pattern will match the first capturing group, not even the pattern _.

To make the match work, use the pattern r(), which does not try to match any capturing groups, or r(_*), which matches regardless of how many groups the regex has.

Upvotes: 2

Related Questions