解析 f 风格的内插字符串以恢复参数
Parse an f-style interpolated string to recover arguments
为 f 样式字符串插值创建补码的最佳方法是什么,即在格式化字符串中解析 arguments/numbers 的方法?
例如
val format = "frame%04d.png"
val i = 123
val out = f"frame$i%04d.png"
assert(out == "frame0123.png")
def parse(s: String, pat: String): Int = ???
val j = parse(out, format)
assert(j == 123)
我知道我可以手动构造一个正则表达式,我只是想知道是否有一个通用的方法来处理 f 样式的内插字符串。
我希望得到像这样简单的东西:
val f"frame$j%04d.png" = out
但是
error: macro method f is not a case class, nor does it have an unapply/unapplySeq member
我发现 this nice post 关于使用插值器作为模式匹配器,所以这是你的起点:
object StringMatcher {
val ZeroFillDec = "%0(\d+)d(.*)".r
val SimpleDec = "%(\d+)d(.*)".r
val String = "%s(.*)".r
def patternize(part: String) = part match {
case ZeroFillDec(len, rest) => f"(\d{${len.toInt}})$rest"
case SimpleDec(len, rest) => f"(\d{1,${len.toInt}})$rest"
case String(rest) => f"(.*)$rest"
case rest => f"(.*)$rest"
}
}
implicit class StringMatcher(sc: StringContext) {
import StringMatcher.patternize
object pat {
def unapplySeq(s: String): Option[Seq[String]] = {
val re = (sc.parts.head ++ (sc.parts.tail map patternize)).mkString.r
re.unapplySeq(s)
}
}
}
使用它,代码
val out = "frame0123_023.png"
val pat"frame$j%04d_$i%03d.png" = out
分配
j: String = 0123
i: String = 023
为 f 样式字符串插值创建补码的最佳方法是什么,即在格式化字符串中解析 arguments/numbers 的方法?
例如
val format = "frame%04d.png"
val i = 123
val out = f"frame$i%04d.png"
assert(out == "frame0123.png")
def parse(s: String, pat: String): Int = ???
val j = parse(out, format)
assert(j == 123)
我知道我可以手动构造一个正则表达式,我只是想知道是否有一个通用的方法来处理 f 样式的内插字符串。
我希望得到像这样简单的东西:
val f"frame$j%04d.png" = out
但是
error: macro method f is not a case class, nor does it have an unapply/unapplySeq member
我发现 this nice post 关于使用插值器作为模式匹配器,所以这是你的起点:
object StringMatcher {
val ZeroFillDec = "%0(\d+)d(.*)".r
val SimpleDec = "%(\d+)d(.*)".r
val String = "%s(.*)".r
def patternize(part: String) = part match {
case ZeroFillDec(len, rest) => f"(\d{${len.toInt}})$rest"
case SimpleDec(len, rest) => f"(\d{1,${len.toInt}})$rest"
case String(rest) => f"(.*)$rest"
case rest => f"(.*)$rest"
}
}
implicit class StringMatcher(sc: StringContext) {
import StringMatcher.patternize
object pat {
def unapplySeq(s: String): Option[Seq[String]] = {
val re = (sc.parts.head ++ (sc.parts.tail map patternize)).mkString.r
re.unapplySeq(s)
}
}
}
使用它,代码
val out = "frame0123_023.png"
val pat"frame$j%04d_$i%03d.png" = out
分配
j: String = 0123
i: String = 023