You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:03:06