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)