【问题标题】:Why does the following program return incorrect boolean values for some inputs?为什么以下程序会为某些输入返回不正确的布尔值?
【发布时间】:2017-06-22 06:58:37
【问题描述】:

因此程序会检查输入的号码是否是有效的美国电话号码。

它广泛使用正则表达式。

一般来说,它可以正常工作。

但对于某些输入,它返回无效的布尔值。为什么会这样?

输入:

  1. “1 (555) 555-5555”应该返回true,但实际上返回false。
  2. “(555)555-5555”应该返回true,但实际上返回false。
  3. “1(555)555-5555”应该返回true,但实际上返回false。
  4. “(6505552368)”应该返回false,但实际上返回true。
  5. “27576227382”应该返回false,但实际上返回true。
  6. "(555-555-5555" 应该返回false,但实际上返回true。

以下是有效的美国电话号码格式列表:

  1. 555-555-5555
  2. (555)555-5555
  3. (555) 555-5555
  4. 555 555 5555
  5. 5555555555
  6. 1 555 555 5555

function telephoneCheck(str) {
  // Good luck!
  var regexArr = ["[0-9]{3}-[0-9]{3}-[0-9]{4}",
"([0-9]{3})[0-9]{3}-[0-9]{4}",
"1{1}([0-9]{3})[0-9]{3}-[0-9]{4}",
"[0-9]{3} [0-9]{3} [0-9]{4}",
"[1]{1} [0-9]{3} [0-9]{3} [0-9]{4}",
"1 ([0-9]{3}) [0-9]{3}-[0-9]{4}",
"[0-9]{10}"];

var cond = false;
  
for(var i = 0;i < regexArr.length;i++){
  var regexObj = new RegExp(regexArr[i], "");
  if(regexObj.test(str)){cond = true;
  break;}
}
 
  return cond;
}



telephoneCheck("555-555-5555");

【问题讨论】:

  • 除其他外,括号是正则表达式语法中的元字符() 字符与括号字符不匹配。相反,它们充当分组运算符。
  • "27576227382" 包含 11 位数字,即 10 + 1 位数字。 “10 位”正则表达式匹配它。如果您不希望它匹配,请使用锚点:"^[0-9]{10}$"
  • @Watilin 这适用于特定的输入,谢谢。
  • 这应该被简化为minimal reproducible example,你只有一个正则表达式与一个字符串进行比较,这实际上可能是一个有用的问题,即如何匹配正则表达式中的括号(尽管这可能是重复的东西)。就目前而言,这个问题对其他人没有多大价值(如果有的话)。
  • 回滚了,因为在编辑后问题变得不那么有用了。如果您有更多要问的问题,请发布一个新问题。

标签: javascript regex algorithm


【解决方案1】:

这是一个单一的正则表达式解决方案,您可以查看它的railroad diagram here

function telephoneCheck(str) {
  return /^(?:1(-| ?)\d{3}\1\d{3}\1\d{4}|\d{3}(-| ?)\d{3}\2\d{4}|1? ?\(\d{3}\) ?\d{3}[- ]\d{4})$/.test(str);
}

console.log("Should pass:");
console.log("1 (555) 555-5555", telephoneCheck("1 (555) 555-5555"));
console.log("(555)555-5555", telephoneCheck("(555)555-5555"));
console.log("1(555)555-5555", telephoneCheck("1(555)555-5555"));
console.log("1-555-555-5555", telephoneCheck("1(555)555-5555"));
console.log("555-555-5555", telephoneCheck("555-555-5555"));
console.log("(555)555-5555", telephoneCheck("(555)555-5555"));
console.log("(555) 555-5555", telephoneCheck("(555) 555-5555"));
console.log("555 555 5555", telephoneCheck("555 555 5555"));
console.log("1 555 555 5555", telephoneCheck("1 555 555 5555"));
console.log("5555555555", telephoneCheck("5555555555"));
console.log("Should fail:");
console.log("(6505552368)", telephoneCheck("(6505552368)"));
console.log("27576227382", telephoneCheck("27576227382"));
console.log("(555-555-5555", telephoneCheck("(555-555-5555"));
console.log("1-(555)-555-5555", telephoneCheck("1-(555)-555-5555"));
console.log("1(555)5555555", telephoneCheck("1(555)5555555"));
console.log("1 555 5555555", telephoneCheck("1 555 5555555"));
console.log("1-555-5555555", telephoneCheck("1-555-5555555"));
console.log("1 555 555-5555", telephoneCheck("1 555 555-5555"));
console.log("1-555 555 5555", telephoneCheck("1-555 555 5555"));
console.log("1555-555-5555", telephoneCheck("1555-555-5555"));
console.log("1 (555 555-5555", telephoneCheck("1 (555 555-5555"));
console.log("1 555) 555-5555", telephoneCheck("1 555) 555-5555"));
console.log("1-5555555555", telephoneCheck("1-5555555555"));
.as-console-wrapper {
  max-height: 100% !important;
}

如果有人可以缩短正则表达式,请随时在 cmets 中发帖,我会更新。

【讨论】:

  • @NarcisNeacsu 我见过的最垃圾(有效)评论...我的更新是否解决了所有这些问题?
  • 这对我不起作用,我仍然得到一些无效的返回值。以下是具有有效美国电话号码格式的列表:555-555-5555; (555)555-5555; (555) 555-5555; 555 555 5555; 5555555555; 1 555 555 5555;
  • 这不是更短,但我建议^(?:1 ?)?(?:\(\d{3}\)|\d{3})[ -]?\d{3}[ -]?\d{4}$ 实际操作:regex101.com/r/Rl8Loi/1
  • @Watilin 这解决了一些输入,但是仍然有一些无效的返回值。
  • @NarcisNeacsu 你能告诉我哪些吗?也许为我们提供您的完整样品集。作为一个非美国人,我不知道什么是有效的美国电话号码。
【解决方案2】:

您需要一个反冲\ 来转义圆括号(否则它们被解释为分组符号)和另一个反冲,因为您将正则表达式括在引号中,所以\\(

另外,您可以尝试将不同的正则表达式统一为一个,例如使用

"1\\s*\\([0-9]{3}\\)\\s*[0-9]{3}-[0-9]{4}"

代替

"1{1}\\([0-9]{3}\\)[0-9]{3}-[0-9]{4}"

"1 \\([0-9]{3}\\) [0-9]{3}-[0-9]{4}"

function telephoneCheck(str) {
  // Good luck!
  var regexArr = [
"[0-9]{3}-[0-9]{3}-[0-9]{4}",
"\\([0-9]{3}\\)[0-9]{3}-[0-9]{4}",
//"1{1}\\([0-9]{3}\\)[0-9]{3}-[0-9]{4}",
"[0-9]{3} [0-9]{3} [0-9]{4}",
"[1]{1} [0-9]{3} [0-9]{3} [0-9]{4}",
//"1 \\([0-9]{3}\\) [0-9]{3}-[0-9]{4}",
"1\\s*\\([0-9]{3}\\)\\s*[0-9]{3}-[0-9]{4}",
"[0-9]{10}"];

var cond = false;
  
for(var i = 0;i < regexArr.length;i++){
  var regexObj = new RegExp(regexArr[i], "");
  if(regexObj.test(str)){cond = true;
  break;}
}
 
  return cond;
}



console.log(telephoneCheck("1 (555) 555-5555"));

【讨论】:

  • 做了这个修改后,还是有一些无效的返回值: 1)telephoneCheck("(6505552368)")应该返回false,实际上返回true; 2)telephoneCheck("-1 (757) 622-7382") 应该返回false,实际上返回true; 3)telephoneCheck("27576227382") 应该返回false,实际上返回true; 4)telephoneCheck("2(757)622-7382") 应该返回false,实际上返回true; 5)telephoneCheck("(555-555-5555") 应该返回false,实际上返回true。
  • 您需要针对所有特殊情况微调您的正则表达式
猜你喜欢
  • 1970-01-01
  • 2020-03-21
  • 2013-08-10
  • 2020-01-17
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多