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

Scala读取SQL文件时正则跨换行匹配失败问题求解

问题根因

核心问题是你调用了Source.fromFile(fname).getLines()方法,该方法会逐行读取文件内容,自动剔除每行末尾的换行符,返回的每一条line变量都仅包含单行内容。你的目标SQL语句是跨两行编写的,表名和ADD CONSTRAINT片段分别属于两个独立的line,因此无论怎么调整换行符匹配规则,都不可能在单行内容中匹配到跨两行的目标片段。

修复方案

方案1:读取整个文件为单个字符串匹配

适合文件体积不大的场景,直接将全量文件内容拼接为单个字符串再执行正则匹配,天然支持跨行识别。调整后代码示例:

import scala.util.matching.Regex
import java.io.File
import scala.io.Source

object Hello extends App {
  // 正则优化:用字符组替代|性能更高,raw字符串避免反斜杠二次转义
  val primaryKeyConstraintNameCatchingRegex: Regex = 
    raw"ALTER TABLE ONLY\s+([a-z_]+\.[a-z_]+)\s+ADD CONSTRAINT\s+([a-z_]+)\s+PRIMARY KEY".r

  def readFile: Unit = {
    val fname = "dump.sql"
    // 读取全量文件内容为单个字符串
    val fileContent = Source.fromFile(fname).mkString
    // 遍历所有匹配结果
    primaryKeyConstraintNameCatchingRegex.findAllMatchIn(fileContent).foreach { m =>
      val fullTableName = m.group(1)
      val pkConstraintName = m.group(2)
      println(s"表${fullTableName}的主键约束为:${pkConstraintName}")
    }
  }

  readFile
}

注:\s本身已经包含换行符、回车符、制表符、空格等所有空白字符,不需要单独匹配\r或\n。

方案2:逐行读取时拼接上下文

如果文件体积过大不适合一次性读入内存,可以在逐行读取时存储上一行的上下文,当识别到上一行是ALTER TABLE ONLY开头的语句时,拼接当前行内容再做匹配,避免内存占用过高。

额外异常现象解释

[a-z_]+(\.[a-z_]+)\s*A能匹配、[a-z_]+(\.[a-z_]+)\s*ADD不能匹配的原因和上文一致:A可能刚好是表名所在行末尾的单个字符,而ADD属于下一行的内容,逐行匹配时自然无法识别到跨行的ADD片段。

内容的提问来源于stack exchange,提问作者zmerr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:36:03