Scala正则提取含逗号引号属性值并映射至Case Class
处理带引号内逗号的属性字符串并映射到Scala Case Class
这个问题的核心难点在于属性值里包含带逗号的引号字符串,普通按逗号分割肯定会把引号里的逗号当成分隔符,导致解析出错。我给你两种实用的Scala解决方案,覆盖不同场景需求:
方案一:正则表达式精准匹配
正则可以精准识别引号包裹的内容,避免误分割。我们可以写一个匹配key=value模式的正则,其中value支持带引号(内部允许逗号)或不带引号的格式。
import scala.util.matching.Regex case class Row(id: String, location: String, desc: String) val s = """id=id1,desc="a description, details",location="a location"""" // 匹配key=value的正则:key为字母数字下划线,value要么是带引号(内部可含逗号)的内容,要么是不带引号的非逗号内容 val attrRegex: Regex = """(\w+)=(".*?"|[^,]+)""".r // 提取所有匹配项,转换为属性名-值的Map val attrMap = attrRegex.findAllMatchIn(s).map { matchResult => val key = matchResult.group(1) // 去掉value的首尾引号(如果存在的话) val value = matchResult.group(2).stripPrefix("\"").stripSuffix("\"") key -> value }.toMap // 映射到Case Class val row = Row( id = attrMap("id"), location = attrMap("location"), desc = attrMap("desc") ) println(row) // 输出:Row(id1,a location,a description, details)
正则逻辑说明
(\w+):匹配属性名,支持字母、数字和下划线(".*?"|[^,]+):分支匹配逻辑".*?":用非贪婪模式匹配带双引号的内容,确保只匹配到当前属性的闭合引号[^,]+:匹配不带引号的、不含逗号的属性值
方案二:用CSV解析库处理复杂场景
如果你的字符串格式涉及更多边缘情况(比如值里有转义引号、换行符),用成熟的CSV解析库会更健壮。这里以scala-csv为例:
首先在build.sbt添加依赖:
libraryDependencies += "com.github.tototoshi" %% "scala-csv" % "1.3.10"
然后编写解析代码:
import com.github.tototoshi.csv._ import java.io.StringReader case class Row(id: String, location: String, desc: String) val s = """id=id1,desc="a description, details",location="a location"""" // 先将key=value格式转换为CSV的表头+行数据格式 val (headers, values) = s.split(",").map { attr => // 按第一个等号分割,避免属性值里包含等号的情况 val Array(key, value) = attr.split("=", 2) (key, value.stripPrefix("\"").stripSuffix("\"")) }.unzip // 构造标准CSV内容 val csvContent = s"${headers.mkString(",")}\n${values.mkString(",")}" // 解析CSV并映射到Case Class val reader = CSVReader.open(new StringReader(csvContent)) val csvRows = reader.allWithHeaders() reader.close() val row = Row( id = csvRows.head("id"), location = csvRows.head("location"), desc = csvRows.head("desc") ) println(row) // 输出:Row(id1,a location,a description, details)
这个方案的优势是能自动处理转义字符(比如desc="He said ""hello"" "这种带转义引号的内容),正则方案在这类场景下需要额外调整规则。
额外注意事项
- 确保Case Class的字段名和字符串中的属性名一致,若大小写不同,可在映射时手动转换(比如
attrMap("ID").toLowerCase) - 如果字符串中属性顺序不固定,用Map或CSV表头映射的方式最稳妥,不需要依赖顺序
内容的提问来源于stack exchange,提问作者elm
相关产品推荐
相关产品推荐

