如何用正则表达式实现电话号码部分字符替换为*的掩码效果?
解决电话号码掩码问题的正确正则方案
你的核心问题是原正则没有排除括号内的数字,且没有精准控制括号外数字的替换范围(仅保留前2位和最后2位)。下面是具体的解决方案:
明确掩码规则
- 括号
()内的数字完全保留,不做任何替换 - 括号外的数字:
- 保留前2位数字
- 保留最后2位数字
- 中间所有数字替换为
* - 原有的非数字分隔符(空格、
-等)保持不变
原正则的问题分析
你使用的(?<!\()\d(?!\d?$)会匹配所有不在(之后的数字(且不是倒数第一个数字),这就导致括号内的123中,2和3因为前面不是(,会被错误替换成*,最终得到+(1**) ***-***45,不符合预期。
正确实现方案
我们需要先区分括号内/外的内容,只处理括号外的数字,并且精准控制替换范围。以下是两种常见语言的实现:
Python 实现
import re def mask_phone_number(phone): # 提取括号外的所有数字序列 non_parentheses_digits = re.findall(r'(?<=\))\d|\d(?=\()', phone) total_digits = len(non_parentheses_digits) # 数字少于等于4位时无需掩码 if total_digits <= 4: return phone # 标记哪些数字需要保留,哪些替换为* digit_map = {} for idx in range(total_digits): if idx < 2 or idx >= total_digits - 2: digit_map[idx] = non_parentheses_digits[idx] else: digit_map[idx] = '*' # 遍历原字符串,构建结果 result = [] in_parentheses = False current_digit_idx = 0 for char in phone: if char == '(': in_parentheses = True result.append(char) elif char == ')': in_parentheses = False result.append(char) elif in_parentheses: result.append(char) elif char.isdigit(): result.append(digit_map[current_digit_idx]) current_digit_idx += 1 else: result.append(char) return ''.join(result) # 测试示例 print(mask_phone_number('+(123) 123-12345')) # 输出:+(123) 12*-***45 print(mask_phone_number('+(123) 123 12 12345')) # 输出:+(123) 12* ** ***45
JavaScript 实现
function maskPhoneNumber(phone) { // 提取括号外的所有数字 const nonParenthesesDigits = phone.match(/(?<=\))\d|\d(?=\()/g) || []; const totalDigits = nonParenthesesDigits.length; if (totalDigits <= 4) return phone; let currentIndex = 0; // 替换括号外的目标数字 return phone.replace(/(?<=\))\d|\d(?=\()/g, () => { currentIndex++; // 保留前2位和最后2位,其余替换为* if (currentIndex <= 2 || currentIndex > totalDigits - 2) { return nonParenthesesDigits[currentIndex - 1]; } return '*'; }); } // 测试示例 console.log(maskPhoneNumber('+(123) 123-12345')); // 输出:+(123) 12*-***45 console.log(maskPhoneNumber('+(123) 123 12 12345')); // 输出:+(123) 12* ** ***45
纯正则替换方案(无回调)
如果你的环境不支持正则回调,可以分三步处理:
- 先把括号内的内容临时替换为占位符,避免干扰
- 对括号外的数字进行掩码处理
- 恢复括号内的内容
示例(Python):
import re def mask_phone_simple(phone): # 第一步:替换括号内内容为占位符 placeholder = "TEMP_PAREN_CONTENT" temp = re.sub(r'\((\d+)\)', placeholder, phone) # 提取括号外的数字 digits = re.findall(r'\d', temp) total = len(digits) if total <=4: return phone # 生成掩码后的数字序列 masked_digits = digits[:2] + ['*']*(total-4) + digits[-2:] # 替换回数字 idx =0 result = [] for c in temp: if c.isdigit(): result.append(masked_digits[idx]) idx +=1 else: result.append(c) # 恢复括号内内容 original_paren = re.search(r'\((\d+)\)', phone).group(1) return ''.join(result).replace(placeholder, f'({original_paren})') # 测试 print(mask_phone_simple('+(123) 123-12345')) # 输出:+(123) 12*-***45
内容的提问来源于stack exchange,提问作者Yevhenii Avram
相关产品推荐
相关产品推荐

