Группа захвата 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?


person Geo    schedule 16.06.2010    source источник


Ответы (4)


Вот пример того, как вы можете получить доступ к group(1) каждого совпадения:

val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).matchData foreach {
   m => println(m.group(1))
}

Это напечатает "483" (как видно на ideone.com).


Вариант обхода

В зависимости от сложности шаблона вы также можете использовать обходные пути, чтобы только соответствовать нужной части. Это будет выглядеть примерно так:

val string = "one493two483three"
val pattern = """(?<=two)\d+(?=three)""".r
pattern.findAllIn(string).foreach(println)

Выше также печатается "483" (как показано на ideone.com).

использованная литература

person polygenelubricants    schedule 16.06.2010
comment
Вы также можете использовать pattern.findAllMatchIn(string).foreach... вместо этого - person ruhong; 13.09.2017

Начиная с 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"
person Xavier Guihot    schedule 26.06.2019

Вы хотите посмотреть на group(1), сейчас вы смотрите на group(0), что представляет собой «всю совпадающую строку».

См. это руководство по регулярному выражению.

person Stephen    schedule 16.06.2010
comment
Можете ли вы проиллюстрировать ввод, который я предоставил? Я пытался вызвать group(1) для того, что возвращает findAllIn, но получаю исключение IllegalStateException. - person Geo; 16.06.2010

person    schedule
comment
Это самый простой способ на сегодняшний день. Вы используете объект регулярного выражения (шаблон) в совпадении/кейсе и извлекаете группу в переменную a483. Проблема в этом случае заключается в том, что шаблон должен иметь подстановочные знаки с обеих сторон: val pattern = .*two(\d+)three.*.r - person makingthematrix; 02.02.2016
comment
да. Я не думаю, что вышеизложенное сразу понятно, но как только вы поймете, что это назначение группы соответствия цифр переменной «a483», тогда это обретет больше смысла. Может быть, переписать более понятным образом? - person Brian Agnew; 03.03.2016
comment
Это способ scala с регулярным выражением. Для людей, которые не понимают волшебства этого ответа, попробуйте выполнить поиск экстрактора регулярных выражений scala или scala unapply regex и т. д. - person JasonWayne; 07.07.2016
comment
семантика непонятна. это первое, последнее или случайное совпадение из строки? - person user239558; 12.06.2018