身份证校验、CIDR 计算、二维码:DuckDB 也能跑
DuckDB 这几年以嵌入式分析数据库的身份,在开发者社区里攒了不少口碑。单文件、零配置、SQL 跑 CSV 和 Parquet,这些能力让它成了数据分析师的新宠。
但如果你需要校验身份证号、计算 CIDR 子网、或者解析一本书的目录——DuckDB 本身做不到。它的内置函数集中在聚合、字符串、日期这些通用领域,涉及中国数据校验、网络协议、文件格式解析这些场景,就得自己写扩展。
alitrack/duckdb-luajit-libs 就是补这个缺的。它是一组用 Lua 写的 DuckDB UDF 库,一条 SQL 装完,38 个库覆盖了校验、文档、编码、优化求解等能力。本文挑其中 8 个实用工具库,看看它们让 DuckDB 多了哪些"本来做不到"的技能。
数据校验:中国数据格式全家桶
cncheck 库是纯 Lua 实现的中国数据校验位全家桶。五个函数覆盖了身份证、统一社会信用代码、银行卡号、手机号,以及身份证信息提取。
身份证校验走 GB11643 标准,加权求和校验位,支持 X 结尾,兼容 15 位旧版自动升级。统一社会信用代码走 GB32100 的 31 字符集 mod 31 校验。银行卡号走 Luhn 算法,覆盖 13 到 19 位。手机号识别 1[3-9] 号段。
id_extract 能从身份证号直接提取区划代码、出生日期和性别。
所有函数都是纯 Lua 实现,零外部依赖。11 个回归用例全部通过。
用法很简单,一条 SQL 注册:
SELECT * FROM luajit_module(mode := 'install', sql_name := 'cncheck');
SELECT luajit_s('cncheck', '{"op":"id_card","val":"11010519491231002X"}');
-- → {"valid":true,"info":"校验通过"}
文本处理:中文友好的字符串相似度
fuzzy 库提供字符串相似度和距离计算,全部纯 Lua 实现,且是 UTF-8 代码点感知。
它包含编辑距离(lev)、归一化编辑距离(normlev)、Jaro 距离、Jaro-Winkler 距离(jaro/jw),以及一个通用指标选择器(sim)和候选列表打分排序器(simrank)。
中文场景下,代码点感知的意义很大。举个例子:按字节处理时,"王小明"和"王小民"的 Jaro-Winkler 距离是 1.0(完全一样),因为两个名字的字节序列在中文编码下被错误对齐。按代码点处理,结果是 0.8889,这才是人类直觉上正确的差异。
9 个回归用例全部通过。
markdown 库则从另一个方向处理文本——它能把 Markdown 文档的结构提取出来:标题树(H1-H6)、链接和图片、代码块、嵌套列表、块引用、统计计数,以及纯文本去标签。
一个关键设计:代码块和行内代码里的 # 号不会被误判为标题。7 个回归用例全过。
网络工具:CIDR 计算
cidr 库提供 IPv4 和 IPv6 的 CIDR 工具集。纯 Lua 实现,IPv4 走 32 位整数运算,IPv6 走 128 位。
包含的函数:version 检测地址版本、ip2int 转整数、int2ip 转回点分十进制、in_cidr 判断 IP 是否在 CIDR 内、cidr_info 展开 CIDR 详细信息、classify 分类地址类型、net 算网络地址、broadcast 算广播地址。
这个库和 Python 标准库 ipaddress 做了交叉校验。140 个测试用例和 Python 结果完全一致,唯一差异在 141 个测试中:Python 将 1:2:3:4:5:6:7:8 这个地址误判为保留地址,cidr 库正确识别为非保留。
文件处理:日志、文件、电子书、二维码
log 库是一个日志归一化表函数。它能自动识别五种日志格式——JSON-lines、Nginx access 日志、syslog、Epoch 时间戳行、ISO 时间戳行——然后统一输出为 line_no、ts(统一 ISO8601)、level、msg、kvs(JSON 格式)的结构化表。
5 种格式各有回归用例。
tail_file 库实现增量文件 tail。它是纯 Lua 的无状态偏移状态机,从上次读取的字节偏移位置继续读,只返回新增行。输出格式是 {offset, count, lines}。
支持未完结行的暂存(下次补全)、文件截断或重建时自动重置偏移、max 参数限制返回条数。5 个回归用例。
epub 库更特别——它不依赖任何外部解析器,内嵌了 ZIP 中央目录解析和 raw inflate 解压,完全自包含。
它能解析 EPUB 电子书的元数据(标题、作者、语言、标识符、出版社、日期、版本号)、目录(EPUB2 的 NCX 和 EPUB3 的 nav type=toc 都支持),以及正文文本(章节去标签纯文本)。
qr 库也是自包含的纯 Lua 实现,不需要任何外部二维码库。它支持 Byte 模式(任意 UTF-8 文本)、四种纠错级别(L/M/Q/H),并且会自动选择 penalty 最小的 mask 图案。
输出形式有四种:matrix 矩阵、svg 矢量图、ascii 字符画、info 信息汇总,以及 codewords 码字原始数据。
和 python-qrcode 做了交叉校验,codewords 逐字节完全一致。
一条 SQL 装完
这些库的安装方式完全一致。DuckDB 里先加载 luajit 扩展,然后一条 SQL 安装:
LOAD '/path/to/luajit.duckdb_extension';
SELECT * FROM luajit_module(mode := 'install', sql_name := 'fuzzy');
SELECT luajit_s('fuzzy', '{"op":"jw","a":"王小明","b":"王小民"}');
全部 38 个库都走同一个 INSTALL 协议,从 GitHub 的 INDEX 仓库自动拉取。不需要 pip install、npm install、cargo build——DuckDB 内部一条 SQL 即装即用。
这 8 个库只是 duckdb-luajit-libs 的一部分。还有 iconv 编码转换、llm_extract 大模型提取、inv_ofd 数电发票解析、zip 容器工具、base64/crc32/uuid 等基础函数,以及更复杂的 incremental 增量加载、scd2 缓慢变化维度、甚至 highs 线性规划求解器。
DuckDB 的定位是"嵌入式分析数据库",但有了 Lua UDF 扩展,它从一个"SQL 查询引擎"变成了一个"可编程的数据处理平台"。你不需要写 C 扩展,不需要编译,不需要装包管理器——一条 SQL 装完,直接用。
参考来源
GitHub: alitrack/duckdb-luajit-libs
luajit 扩展: duckdb/duckdb-luajit (社区扩展)
GB11643-1999 公民身份号码
GB32100-2015 统一社会信用代码
Luhn 算法 (ISO/IEC 7812)
Python ipaddress 标准库 (交叉校验)
python-qrcode (交叉校验)