Соответствие регулярному выражению в Scala
Я довольно часто сопоставляю строки с регулярными выражениями. В Java:
java.util.regex.Pattern.compile( "\ W +" ). Matcher ( "this_is" ). Соответствует
Уч. Scala имеет много альтернатив.
-
"\\w+".r.pattern.matcher("this_is").matches
-
"this_is".matches("\\w+")
-
"\\w+".r unapplySeq "this_is" isDefined
-
val R = "\\w+".r; "this_is" match { case R() => true; case _ => false}
Первый такой же тяжелый, как и код Java.
Проблема со вторым заключается в том, что вы не можете предоставить скомпилированный шаблон ("this_is".matches("\\w+".r")
). (Кажется, это анти-шаблон, поскольку почти каждый раз, когда есть метод, который требует компиляции регулярных выражений, возникает перегрузка, которая принимает регулярное выражение).
Проблема с третьим заключается в том, что она злоупотребляет unapplySeq
и, следовательно, является загадочной.
Четвертое отлично при разложении частей регулярного выражения, но слишком тяжело, когда вам нужен только логический результат.
Я пропустил простой способ проверить совпадения с регулярным выражением? Есть ли причина, почему String#matches(regex: Regex): Boolean
не определен? На самом деле, где String#matches(uncompiled: String): Boolean
определено?
Ответы
Ответ 1
Вы можете определить шаблон следующим образом:
scala> val Email = """(\w+)@([\w\.]+)""".r
findFirstIn
вернет Some[String]
, если он соответствует, или None
.
scala> Email.findFirstIn("[email protected]")
res1: Option[String] = Some([email protected])
scala> Email.findFirstIn("test")
rest2: Option[String] = None
Вы даже можете извлечь:
scala> val Email(name, domain) = "[email protected]"
name: String = test
domain: String = example.com
Наконец, вы также можете использовать обычный метод String.matches
(и даже переработать ранее определенный Email Regexp
:
scala> "[email protected]".matches(Email.toString)
res6: Boolean = true
Надеюсь, это поможет.
Ответ 2
Я создал небольшой шаблон "Pimp my Library" для этой проблемы. Возможно, это поможет вам.
import util.matching.Regex
object RegexUtils {
class RichRegex(self: Regex) {
def =~(s: String) = self.pattern.matcher(s).matches
}
implicit def regexToRichRegex(r: Regex) = new RichRegex(r)
}
Пример использования
scala> import RegexUtils._
scala> """\w+""".r =~ "foo"
res12: Boolean = true
Ответ 3
Я обычно использую
val regex = "...".r
if (regex.findFirstIn(text).isDefined) ...
но я думаю, что это довольно неудобно.
Ответ 4
В настоящее время (август 2014 г., Scala 2.11) @David отвечает нормой.
Однако, похоже, что интерполятор строк r."..."
может помочь в этом. См. Как сопоставить шаблон с использованием регулярного выражения в Scala?