Scala группа захвата с использованием регулярного выражения
Скажем, у меня есть этот код:
val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).foreach(println)
Я ожидал, что findAllIn
вернется только 483
, но вместо этого он вернет two483three
. Я знаю, что я мог бы использовать unapply
для извлечения только этой части, но мне пришлось бы иметь шаблон для всей строки, например:
val pattern = """one.*two(\d+)three""".r
val pattern(aMatch) = string
println(aMatch) // prints 483
Есть ли другой способ достижения этого, без непосредственного использования классов из java.util
и без использования unapply?
Ответы
Ответ 1
Вот пример того, как вы можете получить доступ к group(1)
каждого соответствия:
val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).matchData foreach {
m => println(m.group(1))
}
Отпечатает "483"
(как показано на ideone.com).
Вариант поиска
В зависимости от сложности шаблона вы также можете использовать lookarounds, чтобы соответствовать только той части, которую вы хотите. Это будет выглядеть примерно так:
val string = "one493two483three"
val pattern = """(?<=two)\d+(?=three)""".r
pattern.findAllIn(string).foreach(println)
Вышеупомянутое также печатает "483"
(как показано на ideone.com).
Ссылки
Ответ 2
val string = "one493two483three"
val pattern = """.*two(\d+)three.*""".r
string match {
case pattern(a483) => println(a483) //matched group(1) assigned to variable a483
case _ => // no match
}
Ответ 3
Вы хотите посмотреть group(1)
, вы в настоящее время смотрите на group(0)
, который является "всей совпадающей строкой".
Смотрите это учебное пособие по регулярному выражению.
Ответ 4
def extractFileNameFromHttpFilePathExpression(expr: String) = {
//define regex
val regex = "http4.*\\/(\\w+.(xlsx|xls|zip))$".r
// findFirstMatchIn/findAllMatchIn returns Option[Match] and Match has methods to access capture groups.
regex.findFirstMatchIn(expr) match {
case Some(i) => i.group(1)
case None => "regex_error"
}
}
extractFileNameFromHttpFilePathExpression(
"http4://testing.bbmkl.com/document/sth1234.zip")
Ответ 5
Начиная с Scala 2.13
, в качестве альтернативы решениям регулярных выражений, также возможно сопоставить шаблон с String
, не применяя интерполятор строк:
"one493two483three" match { case s"${x}two${y}three" => y }
// String = "483"
Или даже:
val s"${x}two${y}three" = "one493two483three"
// x: String = one493
// y: String = 483
Если вы ожидаете несоответствующий ввод, вы можете добавить шаблон защиты по умолчанию:
"one493deux483three" match {
case s"${x}two${y}three" => y
case _ => "no match"
}
// String = "no match"