ChatGPT解决这个技术问题 Extra ChatGPT

如何检查字符串是否完全匹配 Scala 中的正则表达式?

假设我有一个想要匹配许多字符串的正则表达式模式。

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 } 看起来比使用底层模式对象更好。

N
Nick

回答我自己的问题,我将使用“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 在这种情况下读起来不太好。


我也用函数 misses 拉皮条。匹配和不匹配 :-) 不得不写 !s.matches(r) 而不是 s misses r 太烦人了。唔
@polygenelubricants 建议的内置 "5" matches "\\d" 怎么样?
数据匹配模式,反之亦然。 Regex 上的 scaladoc 对“匹配”缺少布尔值有很大的影响。就个人而言,我认为您已经将一个不错的匹配换成了一个更笨重的 if-else。如果您不关心组,请使用 case r(_*) =>
必须有一种方法可以在不导入外部库的情况下做到这一点......
@JameelaHuq 访问这个问题的人会对 2.13 感到满意,Regex 最终得到了匹配。 github.com/scala/scala/pull/6521
p
polygenelubricants

我不太了解 Scala,但看起来你可以这样做:

"5".matches("\\d")

参考

http://langref.org/scala/pattern-matching/matching


好吧,这行得通,但缺点是每次尝试匹配时都会编译模式。出于性能原因,我想避免这种情况。
@mkneissl:那么看起来您的 .pattern.matcher(text).matches 是要走的路。如果 Scala 支持,您可以在某些实用方法或重载运算符或其他东西下隐藏详细程度。
谢谢,这就是我要做的,看看我的答案。我希望回答自己的问题是 Stack Overflow 上公认的行为...... Meta 说它是......
@ed。那甚至更慢更粗鲁,那为什么呢?
作为参考给出的链接已损坏
V
Vasil Remeniuk

对于完整匹配,您可以使用 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

虽然是这样,但 unapply 和 unapplySeq 的主要用途隐含在 match 块的 case 中。
J
Jack
  """\d""".r.unapplySeq("5").isDefined            //> res1: Boolean = true
  """\d""".r.unapplySeq("a").isDefined            //> res2: Boolean = false

唔。为什么要在两年后发布 stackoverflow.com/a/3022478/158823 的副本?
您最初的问题要求以“true”或“false”结尾的结果,而不是“Some”或“None”。据我所知,isDefined 2 年前不是图书馆的一部分,但也许它是。无论如何,我的答案不是重复的;-)
我明白了,它不是重复的。对不起。
没有问题 ;-) 我的错误,我应该解释为什么我在回答中使用 isDefined 。仅仅给出代码作为答案通常是一个坏主意,所以这是我的坏主意。
D
Daniel C. Sobral

答案在正则表达式中:

val Digit = """^\d$""".r

然后使用现有方法之一。


我不认为锚是这里的问题。 String/Pattern/Matcher.matches,至少在 Java 中,已经是整个字符串匹配了。我认为问题只是Scala中正则表达式的样式/习语,即那些“现有方法之一”是什么。
@polygenelubricants 好吧,Matcher.matches 是一种异常。好的,它使一些优化成为可能,尽管我不知道 Java 库是否真的利用了它。但是正则表达式表达需要完全匹配的标准方式是使用锚点。由于 Scala 库 提供完全匹配方法,因此正确的方法是使用锚点。要么,要么使用Java库。
锚定不是问题。另请参阅 Vasil 答案中的“123”示例。
@Daniel您可能错过了重点-我的问题是,如果我只需要知道正则表达式是否完全匹配,那么在Scala中表达它的好方法是什么。有很多可行的解决方案,但总而言之,我认为 Regex 中缺少一种方法,它只是做到这一点而没有别的。要回答您评论中的问题:从 unapplySeq 到 findFirstMatch 的区别在于,我必须更改正则表达式以添加锚点。这两种方法都不会立即表达我的意图,也不会返回布尔值,也就是说我必须从 Option 转到 Boolean(没问题,但会增加更多的混乱)。
@mkneissl 我不喜欢Java matches 的概念,但没关系。至于 OptionBoolean,将 nonEmpty 添加到末尾,您将获得 Boolean
S
Sven

使用标准 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