regex - 在 Scala 中将文件中的字符串与案例类匹配的最佳方法是什么?

标签 regex scala recursion case-class fileparsing

我们有一个文件,其中包含我们想要与案例类匹配的数据。我知道足够的知识来暴力破解它,但在 scala 中寻找一种惯用的方法。

给定文件:

#record
name:John Doe
age: 34

#record
name: Smith Holy
age: 33 

# some comment

#record
# another comment
name: Martin Fowler
age: 99 

(两行字段值无效,例如 name:John\n Smith 应该出错)

以及案例类

case class Record(name:String, age:Int) 

我想返回一个Seq类型,例如Stream:

val records: Stream records

我正在研究但到目前为止尚未实现的几个想法是:

  1. 删除所有新行并将整个文件视为一个长字符串。然后 grep match 字符串 "((?!name).)+((?!age).)+age:([\s\d]+)"并为每个匹配创建我的案例类的一个新对象,但是到目前为止,我的正则表达式 foo 很低,无法匹配注释。

  2. 递归思想:遍历每一行找到第一条匹配record的行,然后递归调用函数匹配name,然后是age。当命中下一个记录时,Tail 递归返回 Some(new Record(cumulativeMap.get(name),cumulativeMap.get(age))Nonename之后(即从未遇到过age)

  3. ??更好的主意?

感谢您的阅读!该文件比上面更复杂,但所有规则都是相同的。出于好奇:我正在尝试解析自定义 M3U 播放列表文件格式。

最佳答案

我会使用kantan.regex一个相当简单的基于正则表达式的解决方案。

无需花哨的无定形推导,您可以编写以下内容:

import kantan.regex._
import kantan.regex.implicits._

case class Record(name:String, age:Int) 
implicit val decoder = MatchDecoder.ordered(Record.apply _)
input.evalRegex[Record](rx"(?:name:\s*([^\n]+))\n(?:age:\s*([0-9]+))").toList

这会产生:

List(Success(Record(John Doe,34)), Success(Record(Smith Holy,33)), Success(Record(Martin Fowler,99)))

请注意,此解决方案需要您手动编写解码器,但它通常可以自动派生。如果你不介意无形的依赖,你可以简单地写:

import kantan.regex._
import kantan.regex.implicits._
import kantan.regex.generic._

case class Record(name:String, age:Int) 
input.evalRegex[Record](rx"(?:name:\s*([^\n]+))\n(?:age:\s*([0-9]+))").toList

并得到完全相同的结果。

免责声明:我是该库的作者。

关于regex - 在 Scala 中将文件中的字符串与案例类匹配的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40539743/

相关文章:

javascript - 排序字段的正则表达式

javascript - URL 分割问题

scala - 如何将宏用于简洁、类型安全、未装箱的枚举?

scala - 如何将基于交叉产品的方法添加到 Scala 集合?

python-3.x - 递归导入所有文件夹中的所有 .py 文件

c++ - C++ 标准文档说程序不应调用 main 函数,但我做到了

regex - 在 Emacs 正则表达式中匹配双花括号?

regex - Perl 中的 qr/和 m/有什么区别?

scala - 函数可以接收参数数量不确定的元组吗?

c# - 递归嵌套循环c#