Inexplicable behavior of regular expression

Hi all

Sorry, could anyone explain.
Why this code works properly

val emailRegex: Regex = “(.+)@(.+)\.(.+)”.r

"name@example.com" match {
case emailRegex(userName, domain, topDomain) => println(s"Hi $userName from $domain")
case _ => println(s"This is not a valid email.")
}

Output
Hi name from example

but this one not
val invetoryPattern: Regex = "([0-9]+) in stock at ".r

“2 in stock at Berlin” match {
case invetoryPattern(inventory) => println(s"inventory = $inventory")
case _ => println(s"inventory hasn’t been recognized")
}

Output
inventory hasn’t been recognized

at once

invetoryPattern.findFirstMatchIn(“2 in stock at Berlin”)

res32: Option[scala.util.matching.Regex.Match] = Some(2 in stock at )

Thank you

The reason this fails is the same reason why

java.util.regex.Pattern.compile("([0-9]+) in stock at ").matcher("2 in stock at Berlin").matches

returns false.

Why that returns false though, I haven’t got the foggiest. ("([0-9]+) in stock at ".r).findFirstMatchIn("2 in stock at Berlin") succeeds happily.

The plot thickens.

I have got an answer.
The reason is a pattern must match the whole string.
This code works well.

val invetoryPattern: Regex = “([0-9]+) in stock at .*”.r

“2 in stock at Berlin” match {
case invetoryPattern(inventory) => println(s"inventory = $inventory")
case _ => println(s"inventory hasn’t been recognized")
}
Thank you

1 Like

Glad you found it!

An alternative is then

val inventoryPattern = "^([0-9]+) in stock at ".r

val scrut = "2 in stock at Berlin"

scrut match {
  case inventoryPattern.unanchored(inventory) => println(s"inventory = $inventory")
  case _ => println(s"inventory hasn’t been recognized")
}

Thank you, martijnhoekstra, it looks like what I need.

This is often a surprise. You will find a method unanchored on Regex that removes the need to match the whole string. (And once you have an UnanchoredRegex you can then anchor it to get the original behavior.)