Skip to content
AgileLogics
5 min read

Strings and Regular Expressions

Prerequisites: Pattern matching in depth

Regex basics

.r turns a string into a regular expression:

@main def regexBasics(): Unit =
  val digits = """\d+""".r
  val text = "Order 1042 shipped on 2025-04-22, 3 items"

  println(digits.findFirstIn(text))
  println(digits.findAllIn(text).toList)
  println(digits.replaceAllIn(text, "#"))
  println("abc123".matches("[a-z]+\\d+"))
Some(1042)
List(1042, 2025, 04, 22, 3)
Order # shipped on #-#-#, # items
true

Triple-quoted strings avoid doubling backslashes: """\d+""" instead of "\\d+". Try patterns in the Regex Tester.

Regex in pattern matching

A regex with groups works as a pattern that extracts the groups:

val DateRe = """(\d{4})-(\d{2})-(\d{2})""".r
val LogRe = """(\w+)\s+\[(\w+)\]\s+(.*)""".r

def parse(line: String): String = line match
  case LogRe(time, "ERROR", msg) => s"error at $time: $msg"
  case LogRe(_, level, _)        => s"ignored $level"
  case _                         => "unparseable"

@main def regexMatching(): Unit =
  "2025-04-22" match
    case DateRe(year, month, day) => println(s"day=$day month=$month year=$year")
    case _                        => println("not a date")

  List("0912 [ERROR] disk full", "0913 [INFO] started", "garbage")
    .map(parse).foreach(println)
day=22 month=04 year=2025
error at 0912: disk full
ignored INFO
unparseable

Named groups and all matches

@main def namedGroups(): Unit =
  val email = """(?<user>[\w.]+)@(?<domain>[\w.]+\w)""".r
  val text = "Contact ada@example.com or linus@kernel.org"
  for m <- email.findAllMatchIn(text) do
    println(s"${m.group("user")} at ${m.group("domain")}")
ada at example.com
linus at kernel.org

Useful string helpers

@main def helpers(): Unit =
  val csv = "name, age ,city"
  println(csv.split(",").map(_.trim).toList)
  println("scala".capitalize)
  println("a-b-c".split('-').mkString("[", "|", "]"))
  println("hello world".count(_ == 'o'))
  println("Scala".padTo(8, '.') + "|")
  println("Line1\nLine2".linesIterator.toList)
List(name, age, city)
Scala
[a|b|c]
2
Scala...|
List(Line1, Line2)