我想从包含Scala格式的多个字符串中提取日期(例如2015-01-01
):
val s = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
我知道我可以做基本的字符串split-trim-strip操作来实现这一点,但是在Scala中有更简洁的方法吗?我可以使用一些不错的正则表达式"隐藏的功能" Scala提供这样做?
我尝试了这个但没有取得多大成功:
val s = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
val regex = "(\\d+)-(\\d+)-(\\d+).txt"
val regex(year, month, date) = s
答案 0 :(得分:2)
使用正则表达式提取器
使用模式匹配val regex(a) = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
使用上面的代码而不是下面的代码,因为下面的代码会在运行时导致匹配错误。
.*
而不是正则表达式前面的unanchored
。您可以使用val regex = "(\\d{4}-\\d{2}-\\d{2}).txt".r.unanchored
。
scala> val regex = "(\\d{4}-\\d{2}-\\d{2}).txt".r.unanchored
regex: scala.util.matching.UnanchoredRegex = (\d{4}-\d{2}-\d{2}).txt
scala> val regex(a) = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
a: String = 2015-01-01
Scala REPL
scala> val regex = ".*/(\\d{4}-\\d{2}-\\d{2}).txt".r
regex: scala.util.matching.Regex = .*/(\d{4}-\d{2}-\d{2}).txt
scala> val regex(a) = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
a: String = 2015-01-01
Scala REPL
scala> val str = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
str: String = basedir/somedir/tmp/BLAH/2015-01-01.txt
scala> val regex = ".*/(\\d{4}-\\d{2}-\\d{2}).txt".r
regex: scala.util.matching.Regex = .*/(\d{4}-\d{2}-\d{2}).txt
scala>
| str match {
| case regex(date) => Some(date)
| case _ => None
| }
res21: Option[String] = Some(2015-01-01)
Scala REPL
scala val regex = ".*/(.*)/(\\d{4}-\\d{2}-\\d{2}).txt".r
regex: scala.util.matching.Regex = .*/(.*)/(\d{4}-\d{2}-\d{2}).txt
scala> val s = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
s: String = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
scala> val regex(dir, date) = s
dir: String = "BLAH"
date: String = "2015-01-01"
如果您想匹配目录,那么
{{1}}
答案 1 :(得分:0)
昨天我被谴责解析一些日志文件,每行有三到四个不同的时间表示。
我建议使用最小的正则表达式和最大类型的东西。
$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> val s = "basedir/somedir/tmp/BLAH/2015-01-01.txt"
s: String = basedir/somedir/tmp/BLAH/2015-01-01.txt
scala> val r = raw".*/([\d-]*)\.txt".r
r: scala.util.matching.Regex = .*/([\d-]*)\.txt
scala> val r(date) = s
date: String = 2015-01-01
scala> import java.time._, format._, DateTimeFormatter._
import java.time._
import format._
import DateTimeFormatter._
scala> ISO_LOCAL_DATE.parse(date)
res0: java.time.temporal.TemporalAccessor = {},ISO resolved to 2015-01-01
scala> Instant.from(res0)
java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {},ISO resolved to 2015-01-01 of type java.time.format.Parsed
at java.time.Instant.from(Instant.java:378)
... 27 elided
Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: InstantSeconds
at java.time.format.Parsed.getLong(Parsed.java:203)
at java.time.Instant.from(Instant.java:373)
... 27 more
scala> LocalDate.from(res0)
res2: java.time.LocalDate = 2015-01-01
方便的其他变体:
scala> object LocalDateX { def unapply(s: String): Option[LocalDate] = util.Try(LocalDate.from(ISO_LOCAL_DATE.parse(s))).toOption }
defined object LocalDateX
scala> val r(LocalDateX(date)) = s
date: java.time.LocalDate = 2015-01-01
或
scala> implicit class RContext(val sc: StringContext) {
| object r {
| def apply(args: Any*) = sc.s(args: _*)
| def unapplySeq(s: String) = sc.parts.mkString("(.+)").r.unapplySeq(s)
| }}
defined class RContext
scala> val r".*/${LocalDateX(date)}.txt" = s
date: java.time.LocalDate = 2015-01-01
答案 2 :(得分:-1)
您可以分两行完成。
import java.text.SimpleDateFormat
val date_format = new java.text.SimpleDateFormat("yyyy-MM-dd")
date_format.format(date_format.parse("2017-10-26 09:15:54.127"))
res39: String = 2017-10-26