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

PostgreSQL下用正则表达式从复杂字符串提取最多两位小数的数值

需求背景

该需求产生于对某问题的答复,在我看来该答复仅完成了部分需求。
完整的表结构、测试数据SQL及测试框架可查看对应fiddle示例。
我拥有如下表结构与数据:

CREATE TABLE payment (id INT, amount TEXT NOT NULL);

插入的测试数据如下,注释为预期输出结果:

INSERT INTO payment VALUES                          -- 预期输出结果
(1, 'KES 0.80__asdfa   .80..98..00sadf   '),        --  0.80 或 .8 或 .80
(2, '00 a 0..0...00asafd 0000013..0.85...0000'),    --  0.85 或 .85
(3, '0sf00..0...0 00.000 X013....12.851...0000'),   --  12.85
(4, '000..0...007600.00 0013..12.....0000'),        --  7600
(5, '0afs0 sdff 00...00000.56.....000343..343.0'),  --  0.56 或 .56
(6, 'fs0 sdff 00...0.000710x00.56..asfd0003..3.0'); --  0.56 或 .56,不匹配0.00071或710 

提取规则

我需要从字符串中提取格式为xxxx.yy的有效数值:整数部分位数无限制(可指定整数位数为额外加分项),小数部分最多2位,超出位数可截断,也可通过PostgreSQL内置函数自行取整。
具体规则如下:

  • 规则1:0.80属于第一个符合小数点后保留2位规则的有效数值,直接提取即可
  • 规则2:优先提取0.85而非13,因为13..不符合有效数值格式;如果是13.00(或其他两位小数)则判定为有效,类似13.0.的格式无效
  • 规则3:提取12.85而非12.851,遵循小数部分最多2位的规则
  • 规则4:7600属于有效整数,可直接提取;注意7,600为无效格式,本需求不支持千位分隔符
  • 规则5:0.56为常规有效数值,直接提取
  • 规则6:核心校验规则:需提取0.56,排除0.00071(小数位数不符合要求)与710(后缀带x属于非法数值)。有效数值定义为:连续数字段+小数点+至少2位连续数字,多余小数位可截断

现有方案问题

为方便调试,我也附上了自己的测试fiddle,当前使用的正则如下:

SELECT
  REGEXP_REPLACE(amount, '[^0-9\.]+|\. +|\.0|\.{2,}', '', 'g')
FROM payment;

本问题的测试数据在文末也有展示,也可查看第二份测试fiddle。当前我的正则存在的问题是过于场景定制化,用了太多|分支匹配特定情况,我需要更通用的正则方案,因此发起此问询。

注意事项

  • 测试fiddle中内置了测试框架,可直接验证方案有效性。此前我提过另一正则问题,最终发现PostgreSQL的正则实现存在特殊限制:正向/反向预查约束不能包含反向引用(见官方文档9.7.3.3节),预查内的所有括号均视为非捕获组,导致其他平台可用的正则在PostgreSQL中失效,因此建议大家直接在提供的PostgreSQL fiddle中调试代码,避免浪费时间。
  • PostgreSQL的REGEXP_REPLACE()函数说明:REGEXP_REPLACE(源字符串, 匹配模式, 替换值 [, 标识位])。我当前使用的替换值为空字符串'',并使用了'g'全局标识位,不加该标识位仅会替换第一个匹配项,若需要多轮替换可参考该特性。
  • 我个人也希望借此机会学习正则表达式的使用,此前我不用正则的实现逻辑写了30行代码,用正则后仅需3行,因此希望大家提供方案时能对正则做逐段注释,说明每部分的匹配逻辑,非常感谢。
  • 如果时间允许,也欢迎对我原有fiddle中的正则提出优化建议,其他有用的相关提示也非常欢迎。
    我已尽量将需求描述清楚,若有疑问尤其是PostgreSQL相关的特性问题,我可以随时补充说明。

简化测试数据

用于调试正则的简化测试数据如下:

INSERT INTO payment VALUES
(1,  'KES 0.80'),             
(2,  'KES  0.80'),            
(3,  'KES .80'),           
(4,  'xyzKES 0.80'),          
(5,  'KES . 0.80'),           
(6,  'KES 0.80afasf'),          
(7,  'KES 0.80__asdfa   ..'),
(8,  'KES 0.80..asdfasdf'),
(9,  'KES 0.8.0..asdfasdf'),
(10, 'KES 0.8.0    ..asdfasdf...');

内容的提问来源于stack exchange,提问作者Vérace

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:45:03