使用正则从SQL国家插入语句提取指定字段的匹配问题
问题说明
现有存储国家数据的SQL插入脚本,需要仅保留指定字段生成新的SQL语句,无需保留原语句全量字段。使用正则做数据清洗时存在匹配缺陷:当下一条记录与上一条记录在同一行拼接时,正则无法成功匹配后续记录。
原有方案缺陷
原使用的正则规则:
(\(([0-9]),(['a-zA-Z ]*),(['a-zA-Z ]*)).*
存在3个核心问题:
- 末尾使用贪婪匹配符
.*,会直接吞掉当前行后续所有内容,导致同行拼接的其他记录无法进入匹配流程 - 字段匹配规则仅支持英文字母和空格,无法兼容国家名称中带特殊字符、重音字符的场景
- 冗余捕获了不需要的自增ID字段,输出结果不符合预期
修正后的实现方案
正则匹配规则
替换为以下正则,同时开启全局匹配(g) 标志:
\(\d+,\s*('[^']+',\s*'[^']+')[^)]*\),?
规则逻辑说明:
- 跳过每条记录开头的左括号、数字ID、逗号和空白字符,不做捕获
- 捕获组1精准提取需要保留的两个单引号包裹字段:国家名称、三位国家代码,兼容字段内的空格、特殊字符
- 匹配当前记录剩余内容时,仅匹配到当前记录的闭合右括号即停止,不会越界吞掉同行拼接的后续记录
- 兼容记录末尾可选的逗号分隔符
替换内容
保持替换内容如下即可:
($1, 1, NOW(), NOW()),
匹配效果
无论记录是换行分隔还是同行拼接,都可以准确提取目标字段,输出结果完全符合预期:
('Afghanistan','AFG', 1, NOW(), NOW()), ('Aland Islands','ALA', 1, NOW(), NOW()), ('Albania','ALB', 1, NOW(), NOW()), ('Algeria','DZA', 1, NOW(), NOW()), ('American Samoa','ASM', 1, NOW(), NOW()),
兼容优化
如果数据中存在带转义单引号的字段值(比如'Cote d\'Ivoire'),可以将正则调整为以下版本,兼容转义场景:
\(\d+,\s*('(?:[^'\\]|\\.)*',\s*'(?:[^'\\]|\\.)*')[^)]*\),?
内容的提问来源于stack exchange,提问作者Ihtisham Khan
相关产品推荐
相关产品推荐

