【发布时间】:2016-11-30 05:11:00
【问题描述】:
如何编写表达式来过滤输入,使其格式为 (AAA) 其中 A 是从 0 到 9 的数字。 例如:(123)、(592)、(999)
【问题讨论】:
-
反向引用
(\d)\1*
标签: regex scala escaping character
如何编写表达式来过滤输入,使其格式为 (AAA) 其中 A 是从 0 到 9 的数字。 例如:(123)、(592)、(999)
【问题讨论】:
(\d)\1*
标签: regex scala escaping character
通常你想做的不仅仅是过滤。
scala> val r = raw"\(\d{3}\)".r
r: scala.util.matching.Regex = \(\d{3}\)
scala> List("(123)", "xyz", "(456)").filter { case r() => true case _ => false }
res0: List[String] = List((123), (456))
scala> import PartialFunction.{cond => when}
import PartialFunction.{cond=>when}
scala> List("(123)", "xyz", "(456)").filter(when(_) { case r() => true })
res1: List[String] = List((123), (456))
保留每个输入的所有匹配项:
scala> List("a(123)b", "xyz", "c(456)d").flatMap(s =>
| r.findAllMatchIn(s).map(_.matched).toList)
res2: List[String] = List((123), (456))
scala> List("a(123)b", "xyz", "c(456)d(789)e").flatMap(s =>
| r.findAllMatchIn(s).map(_.matched).toList)
res3: List[String] = List((123), (456), (789))
只保留第一个:
scala> val r = raw"(\(\d{3}\))".r.unanchored
r: scala.util.matching.UnanchoredRegex = (\(\d{3}\))
scala> List("a(123)b", "xyz", "c(456)d(789)e").flatMap(r.unapplySeq(_: String)).flatten
res4: List[String] = List((123), (456))
scala> List("a(123)b", "xyz", "c(456)d(789)e").collect { case r(x) => x }
res5: List[String] = List((123), (456))
保持匹配的整行:
scala> List("a(123)b", "xyz", "c(456)d(789)e").collect { case s @ r(_*) => s }
res6: List[String] = List(a(123)b, c(456)d(789)e)
Java API:
scala> import java.util.regex._
import java.util.regex._
scala> val p = Pattern.compile(raw"(\(\d{3}\))")
p: java.util.regex.Pattern = (\(\d{3}\))
scala> val q = p.asPredicate
q: java.util.function.Predicate[String] = java.util.regex.Pattern$$Lambda$1107/824691524@3234474
scala> List("(123)", "xyz", "(456)").filter(q.test)
res0: List[String] = List((123), (456))
【讨论】:
通常您使用字符串上可用的.r 方法创建正则表达式,例如"[0-9]".r。但是,正如您所注意到的,这意味着您不能插入转义字符,因为解析器认为您想要将转义字符插入字符串,而不是正则表达式。
为此,您可以使用 Scala 的三引号字符串,它可以创建精确字符序列的字符串,包括反斜杠和换行符。
要创建一个像你描述的正则表达式,你可以写"""\(\d\d\d\)""".r。以下是它的使用示例:
val regex = """\(\d\d\d\)""".r.pattern
Seq("(123)", "(---)", "456").filter(str => regex.matcher(str).matches)
【讨论】:
List("(123)", "xyz", "(456)").filter(pattern.asPredicate.test) 或类似的。