假设我有一个想要匹配许多字符串的正则表达式模式。
val Digit = """\d""".r
我只想检查给定的字符串是否完全匹配正则表达式。在 Scala 中执行此操作的好方法和惯用方法是什么?
我知道我可以在正则表达式上进行模式匹配,但在这种情况下,这在语法上不是很令人满意,因为我没有要提取的组:
scala> "5" match { case Digit() => true case _ => false }
res4: Boolean = true
或者我可以回退到底层的 Java 模式:
scala> Digit.pattern.matcher("5").matches
res6: Boolean = true
这也不优雅。
有更好的解决方案吗?
"5" match { case Digit() => true case _ => false }
看起来比使用底层模式对象更好。
回答我自己的问题,我将使用“pimp my library pattern”
object RegexUtils {
implicit class RichRegex(val underlying: Regex) extends AnyVal {
def matches(s: String) = underlying.pattern.matcher(s).matches
}
}
并像这样使用它
import RegexUtils._
val Digit = """\d""".r
if (Digit matches "5") println("match")
else println("no match")
除非有人提出更好的(标准)解决方案。
笔记
我没有拉皮条字符串来限制潜在副作用的范围。
unapplySeq 在这种情况下读起来不太好。
我不太了解 Scala,但看起来你可以这样做:
"5".matches("\\d")
参考
http://langref.org/scala/pattern-matching/matching
.pattern.matcher(text).matches
是要走的路。如果 Scala 支持,您可以在某些实用方法或重载运算符或其他东西下隐藏详细程度。
对于完整匹配,您可以使用 unapplySeq。此方法尝试匹配目标(整个匹配)并返回匹配项。
scala> val Digit = """\d""".r
Digit: scala.util.matching.Regex = \d
scala> Digit unapplySeq "1"
res9: Option[List[String]] = Some(List())
scala> Digit unapplySeq "123"
res10: Option[List[String]] = None
scala> Digit unapplySeq "string"
res11: Option[List[String]] = None
match
块的 case
中。
"""\d""".r.unapplySeq("5").isDefined //> res1: Boolean = true
"""\d""".r.unapplySeq("a").isDefined //> res2: Boolean = false
答案在正则表达式中:
val Digit = """^\d$""".r
然后使用现有方法之一。
String/Pattern/Matcher.matches
,至少在 Java 中,已经是整个字符串匹配了。我认为问题只是Scala中正则表达式的样式/习语,即那些“现有方法之一”是什么。
Matcher.matches
是一种异常。好的,它使一些优化成为可能,尽管我不知道 Java 库是否真的利用了它。但是正则表达式表达需要完全匹配的标准方式是使用锚点。由于 Scala 库不 提供完全匹配方法,因此正确的方法是使用锚点。要么,要么使用Java库。
matches
的概念,但没关系。至于 Option
与 Boolean
,将 nonEmpty
添加到末尾,您将获得 Boolean
。
使用标准 Scala 库和预编译的正则表达式模式和模式匹配(这是 scala 最先进的技术):
val digit = """(\d)""".r
"2" match {
case digit( a) => println(a + " is Digit")
case _ => println("it is something else")
}
更多阅读:http://www.scala-lang.org/api/2.12.1/scala/util/matching/index.html
misses
拉皮条。匹配和不匹配 :-) 不得不写!s.matches(r)
而不是s misses r
太烦人了。唔"5" matches "\\d"
怎么样?case r(_*) =>
。