正则表达式匹配加拿大邮政编码:多匹配位置重置问题求助
解决加拿大邮政编码正则匹配中连续/重叠匹配的捕获问题
问题核心
原正则[A-Z]\d[A-Z]\s*\d[A-Z]\d无法捕获连续或重叠的加拿大邮编,比如在B1A0A0A0中,只能抓到第一个B1A0A0,后面的A0A0A0会被跳过——这是因为正则引擎匹配到一个结果后,会把匹配指针移动到当前匹配的末尾,后面重叠的潜在匹配就被忽略了。
解决方法
使用**零宽度正向预查(lookahead)**包裹捕获组,让正则引擎在不消耗字符的前提下检查所有可能的匹配位置,这样就能捕获所有重叠或连续的邮编。修改后的正则为:
(?=([A-Z]\d[A-Z]\s*\d[A-Z]\d))
(?=...)是零宽度预查:只验证当前位置后方是否符合规则,不会移动匹配指针,所以可以重复检查后续字符。- 内部的捕获组
([A-Z]\d[A-Z]\s*\d[A-Z]\d)负责提取我们需要的邮编内容。
PostgreSQL 实际代码示例
把你的查询更新为以下版本,就能正确返回所有预期匹配:
with barcodes as( select * from (values ('AAAC9B92WLEDH0G5R0Z0|2024-01-01T01:59:39.379-05') , ('SOMETEXTB1A0A0A0OTHERSTUFFB2A 0B0OTHER') , ('SOMETEXTA0A 0A0OTHERSTUFF') )b(barcode) ) select * from barcodes b left join lateral ( SELECT UNNEST( REGEXP_MATCHES( b.barcode , '(?=([A-Z]\d[A-Z]\s*\d[A-Z]\d))' , 'g' ) ) match )t on true;
执行后会得到:
SOMETEXTB1A0A0A0OTHERSTUFFB2A 0B0OTHER对应的匹配:B1A0A0、A0A0A0、B2A 0B0SOMETEXTA0A 0A0OTHERSTUFF对应的匹配:A0A 0A0
关键说明
- 必须保留捕获组:
REGEXP_MATCHES默认返回捕获组的内容,预查本身不会输出匹配文本。 - 全局标志
g不能少:确保扫描整个字符串的所有匹配位置。
内容的提问来源于stack exchange,提问作者Iannick
相关产品推荐
相关产品推荐

