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
相关产品推荐
相关产品推荐

