如何编写正则实现左右括号`(` `)`必须同时至少出现一次才匹配成功
JavaScript电话号码正则校验单括号误匹配问题修复
问题说明
开发JavaScript电话号码校验功能时,编写的正则存在逻辑漏洞:仅包含单个右括号的非法测试用例1 555)555-5555被错误返回true,该场景预期应返回false。
此前尝试添加[()]{0,1}规则实现括号校验,但该写法仅能匹配(或)单独出现的情况,无法满足*(和)必须成对存在、同时出现且各自至少出现一次*的校验要求。
原有错误实现代码如下:
function telephoneCheck(str) { const regex = /^[1]{0,1}[-\s]?[(]?\d{3}[-)\s]?[\s]?[\d]{3}[-\s]?[\d]{4}$/g return regex.test(str) } console.log(telephoneCheck("1 555)555-5555"));
问题根因
- 原有正则将左括号、右括号的匹配规则拆分在独立位置:区号前仅设置
[(]?匹配可选左括号,区号后设置[-)\s]?匹配可选右括号/连字符/空格,两个规则无绑定校验逻辑,导致仅出现单个括号时也能满足匹配条件。 - 正则添加了无必要的全局匹配符
g,在test方法中使用会留存上次匹配的lastIndex指针,连续调用时可能出现匹配结果不稳定的问题。
修复方案
核心调整是将区号部分的括号规则改为分支匹配,仅允许两种合法的区号格式:
- 区号无括号,前后仅允许空格、连字符作为分隔符
- 区号前后同时携带成对的
(和)
修复后可正常拦截单括号的非法格式,完整实现代码如下:
function telephoneCheck(str) { // 移除无意义的g标识,通过分支匹配强制括号成对出现 const regex = /^1?[-\s]?(?:\(\d{3}\)|\d{3})[-\s]?\d{3}[-\s]?\d{4}$/ return regex.test(str) } // 测试校验 console.log(telephoneCheck("1 555)555-5555")); // false 符合预期,拦截单括号非法格式 console.log(telephoneCheck("1 (555)555-5555")); // true 合法成对括号格式 console.log(telephoneCheck("555-555-5555")); // true 合法无括号连字符分隔格式 console.log(telephoneCheck("1 555 555 5555")); // true 合法无括号空格分隔格式
正则规则拆解
^1?:匹配可选的国家码1,等价于原有写法[1]{0,1},写法更简洁[-\s]?:匹配国家码后可选的连字符/空格分隔符(?:\(\d{3}\)|\d{3}):非捕获组,限定区号仅支持两种合法形式:带成对括号的(三位数字)、无括号的三位数字,从规则层面杜绝单括号通过校验的可能[-\s]?:匹配区号后可选的连字符/空格分隔符\d{3}[-\s]?\d{4}$:匹配后续3位号码段+4位号码段,分隔符仅允许可选的连字符/空格
内容的提问来源于stack exchange,提问作者CRISVOSS
相关产品推荐
相关产品推荐

