求PCRE正则表达式:匹配8/9/12位数字并仅保留后4位未掩码
PCRE正则实现指定长度数字串掩码需求
需求
编写PCRE正则,仅匹配数字总数为8、9或12位的字符串(数字间可包含空格、连字符-、逗号,作为分隔符),将除最后4位之外的数字替换为掩码字符(如*),具体规则:
- 8位数字:前4位掩码,保留最后4位
- 9位数字:前5位掩码,保留最后4位
- 12位数字:前8位掩码,保留最后4位
现有问题
你当前编写的正则仅能匹配前5位数字,既满足不了不同长度的掩码要求,也无法处理数字间的分隔符。
解决办法
带分隔符保留的方案(推荐)
通过正则匹配目标串,结合回调函数处理替换,可保留原分隔符的位置:
匹配正则
/(?<=\D|^)([\d\s,-]*)(\d{4})(?=\D|$)/gmi
替换逻辑(PHP示例)
$str = preg_replace_callback( '/(?<=\D|^)([\d\s,-]*)(\d{4})(?=\D|$)/gmi', function($matches) { $fullStr = $matches[1] . $matches[2]; // 提取纯数字部分 $pureDigits = preg_replace('/[\s,-]/', '', $fullStr); $digitLength = strlen($pureDigits); // 仅处理符合长度要求的串 if (!in_array($digitLength, [8, 9, 12])) return $fullStr; // 计算需要掩码的数字数量 $maskCount = $digitLength - 4; // 将前缀部分的指定数量数字替换为* $maskedPrefix = preg_replace('/\d/', '*', $matches[1], $maskCount); return $maskedPrefix . $matches[2]; }, $str );
纯正则替换方案(无回调)
若不想使用回调函数,可分三次替换处理不同长度的字符串:
// 处理8位数字串:替换前4个数字为* $str = preg_replace('/(?<=\D|^)(?:[\s,-]*\d){4}(?=(?:[\s,-]*\d){4}(?:\D|$))/', '****', $str); // 处理9位数字串:替换前5个数字为* $str = preg_replace('/(?<=\D|^)(?:[\s,-]*\d){5}(?=(?:[\s,-]*\d){4}(?:\D|$))/', '*****', $str); // 处理12位数字串:替换前8个数字为* $str = preg_replace('/(?<=\D|^)(?:[\s,-]*\d){8}(?=(?:[\s,-]*\d){4}(?:\D|$))/', '********', $str);
无分隔符简化方案
若不需要保留分隔符,可先去除所有非数字字符,再进行掩码:
// 匹配8/9/12位数字串的前缀部分 /(?<=\D|^)(\d{4})(?=\d{4}$)|(?<=\D|^)(\d{5})(?=\d{4}$)|(?<=\D|^)(\d{8})(?=\d{4}$)/gmi
替换时对应长度替换为掩码:
- 匹配到的4位数字→
**** - 匹配到的5位数字→
***** - 匹配到的8位数字→
********
效果示例
| 原始串 | 掩码后结果 |
|---|---|
| 12345678 | ****5678 |
| 123-456-789 | --789 |
| 1234,5678,9012 | ,,9012 |
| 12 345 6789 | ** *** 6789 |
内容的提问来源于stack exchange,提问作者Kamesh
相关产品推荐
相关产品推荐

