如何使用正则表达式仅匹配给定字符串中的特定字符?

21

我想要一个特定的值,这个值只能是数字且:

  • 长度应为11。

  • 第一位数字应为0。

  • 第二位数字应为1。

  • 第三位数字应为0、1、2或5。

  • 然后匹配从第四位到结尾的任何数字。

  • 如果第三位数字是1,则最后两位数字(第10位和第11位)应相同。

  • 如果第三位数字是2,则第8位和第9位数字应相同。

输入字符串,并期望得到结果。

01012345678          -----> allowed.
0101234a5678         -----> not allowed., letter exists.
01112345688          -----> allowed, 10th, 11st are the same
01112345677          -----> allowed, 10th, 11st are the same
01112345666          -----> allowed, 10th, 11st are the same
01112345689          -----> not allowed..10th, 11st different
01112345-678         -----> not allowed..hyphen exists.
01298765532          -----> allowed..8th, 9th are the same.
01298765732          -----> not allowed, 8th, 9th different.
01298765mm432        -----> not allowed, letter exists.
01500011122          -----> allowed..
020132156456136      -----> not allowed..more than 11 digit.
01530126453333       -----> not allowed..more than 11 digit.
00123456789          -----> not allowed.. second digit not 1.


这是我尝试使用regex101的结果,^01[0125][0-9]{8}$https://regex101.com/r/cIcD0R/1,但它忽略了特定情况,同时也适用于特定情况。
3个回答

27
你可以使用带有2个捕获组和反向引用的替换:
^01(?:[05]\d{8}|1\d{6}(\d)\1|2\d{4}(\d)\2\d\d)$

解释

  • ^ 字符串开始
  • 01 直接匹配数字 01
  • (?: 非捕获组,用于多个可选项
    • [05]\d{8} 匹配数字 0 或 5 后面跟着 8 个数字
    • | 或者
    • 1\d{6}(\d)\1 匹配数字 1,后面跟着 6 个数字,然后捕获一个数字到第一组中,再使用反向引用匹配相同的数字
    • | 或者
    • 2\d{4}(\d)\2\d\d 匹配数字 2,后面跟着 4 个数字,捕获一个数字到第二组中,再使用反向引用匹配相同的数字,最后匹配最后两个数字
  • ) 关闭非捕获组
  • $ 字符串结束

请参考 regex101 demo 进行演示。

const regex = /^01(?:[05]\d{8}|1\d{6}(\d)\1|2\d{4}(\d)\2\d\d)$/;
[
  "01012345678",
  "0101234a5678",
  "01112345688",
  "01112345677",
  "01112345666",
  "01112345689",
  "01112345-678",
  "01298765532",
  "01298765732",
  "01298765mm432",
  "01500011122",
  "020132156456136",
  "01530126453333",
  "00123456789"
].forEach(s => console.log(`${s} => ${regex.test(s)}`))


15

如果您只是想使用正则表达式来过滤某些数字而不显示错误消息,那么本答案可能并不适用于您。

对于验证目的,正则表达式可能不是最佳选择。如果您使用一个巨大的正则表达式,您将会显示一个通用的错误消息。这可能会让用户感到困惑,因为他们部分地符合了一些标准。

相反,将标准分解开来,这样您就可以向用户显示相关的错误消息。

function isValid(input, criteria) {
  const errors = [];
  
  for (const [isValid, error] of criteria) {
    if (!isValid(input)) errors.push(error);
  }
    
  return [!errors.length, errors];
}

const criteria = [
  [input => input.length === 11,
    "must have a length of 11"],
  [input => input.match(/^\d*$/),
    "must only contain digits (0-9)"],
  [input => input[0] === "0",
    "must have 0 as 1st digit"],
  [input => input[1] === "1",
    "must have 1 as 2nd digit"],
  [input => ["0","1","2","5"].includes(input[2]),
    "must have 0, 1, 2 or 5 as 3rd digit"],
  [input => input[2] !== "1" || input[9] === input[10],
    "the 10th and 11th digit must be the same if the 3rd digit is 1"],
  [input => input[2] !== "2" || input[7] === input[8],
    "the 8th and 9th digit must be the same if the 3rd digit is 2"],
];

document.forms["validate-number"].addEventListener("submit", function (event) {
  event.preventDefault();
  
  const form = event.target;
  const inputs = form.elements.inputs.value.split("\n");
  
  inputs.forEach(input => console.log(input, ...isValid(input, criteria)));
});
<form id="validate-number">
<textarea name="inputs" rows="14" cols="15">01012345678
0101234a5678
01112345688
01112345677
01112345666
01112345689
01112345-678
01298765532
01298765732
01298765mm432
01500011122
020132156456136
01530126453333
00123456789</textarea>
<br />
<button>validate</button>
</form>


12

根据您提供的示例,请尝试以下正则表达式。这里是用于该正则表达式的在线演示

^01(?:(?:[05][0-9]{8})|(?:1[0-9]{6}([0-9])\1)|(?:2[0-9]{4}([0-9])\2[0-9]{2}))$

以下是上述正则表达式的JS代码,使用了foreach循环以及其中的test函数。

const regex = /^01(?:(?:[05][0-9]{8})|(?:1[0-9]{6}([0-9])\1)|(?:2[0-9]{4}([0-9])\2[0-9]{2}))$/;
[
  "01012345678",
  "0101234a5678",
  "01112345688",
  "01112345677",
  "01112345666",
  "01112345689",
  "01112345-678",
  "01298765532",
  "01298765732",
  "01298765mm432",
  "01500011122",
  "020132156456136",
  "01530126453333",
  "00123456789"  
].forEach(element => 
  console.log(`${element} ----> ${regex.test(element)}`)
);

说明:为使用的正则表达式添加详细说明。

^01                              ##Matching 01 from starting of the value.
(?:                              ##Starting outer non-capturing group from here.
  (?:                            ##In a non-capturing group
    [05][0-9]{8}                 ##Matching 0 OR 5 followed by any other 8 digits.
  )
  |                              ##Putting OR condition here.
  (?:                            ##In a non-capturing group
    1[0-9]{6}([0-9])\1           ##Matching 1 followed by 6 digits followed by single digit(in a capturing group) and making sure next digit is matching previous.
  )
  |                              ##Puting OR condition here.
  (?:                            ##In a non-capturing group matching, 2 followed by 4 digits followed by 1 digit in capturing group followed by it followed by 2 any other digits.
    2[0-9]{4}([0-9])\2[0-9]{2}
  )
)$                               ##Closing outer non-capturing grouo here at the last of the value.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接