【问题标题】:Regexp for check that string contains mixed characters: 0-n digits and 0-m letters用于检查字符串是否包含混合字符的正则表达式:0-n 个数字和 0-m 个字母
【发布时间】:2019-02-11 08:24:44
【问题描述】:

我尝试找到允许我传递具有 0-n 位和 0-m 小写字母的字符串的正则表达式,其中 字母和数字可以混合。不允许使用任何其他字符。据我所知,我不知道如何让“混合”工作

// example n and m values and array with input strings to test
let n=2,m=3; 
let s=["32abc","abc32","a3b2c","3abc2","a2","abcd23","a2b3c4","aa","32","a3b_2c"];

let r=s.map(x=>/[0-9]{2}[a-z]{3}/.test(x));

console.log("curr:", JSON.stringify(r));
console.log("shoud be:   [true,true,true,true,true,false,false,true,true,false]");

【问题讨论】:

  • 我认为您希望 1n/m 重复。你确定预期的结果吗?试试new RegExp("^(?=(?:[^0-9]*[0-9]){1," + n + "})(?=(?:[^a-z]*[a-z]){1," + m + "})")
  • @WiktorStribiżew 我更新问题
  • 在下面查看我的答案。

标签: javascript regex


【解决方案1】:

而不是单个RE,考虑分别测试字母和数字,用全局标志,检查全局匹配数组的长度是否分别为nm

let n = 2,
  m = 3; // example n and m values
let s = ["32abc", "abc32", "a3b2c", "3abc2", "a2", "abcd23", "a2b3c4", "aa", "32"];


let r = s.map(str => (
  /^[0-9a-z]*$/.test(str) &&
  (str.match(/[0-9]/g) || []).length <= n &&
  (str.match(/[a-z]/g) || []).length <= m
));
console.log("current is:", JSON.stringify(r));
console.log("shoud be:   [true,true,true,true,true,false,false,true,true]");

或者,更罗嗦但也许更优雅,不创建一个空的中间数组:

let n = 2,
  m = 3; // example n and m values
let s = ["32abc", "abc32", "a3b2c", "3abc2", "a2", "abcd23", "a2b3c4", "aa", "32"];


let r = s.map((str, i) => {
  const numMatch = str.match(/[0-9]/g);
  const numMatchInt = numMatch ? numMatch.length : 0;
  const alphaMatch = str.match(/[a-z]/g);
  const alphaMatchInt = alphaMatch ? alphaMatch.length : 0;
  return numMatchInt <= n && alphaMatchInt <= m && /^[0-9a-z]*$/.test(str);
});
console.log("current is:", JSON.stringify(r));
console.log("shoud be:   [true,true,true,true,true,false,false,true,true]");

【讨论】:

  • 我认为 OP 的意思是最多 n 数字和m 小写字母。
  • 完美整洁+1
  • 此解决方案的一个问题是它匹配字符串“32_bc” - 不允许使用除数字和低字母以外的其他字符
  • @KamilKiełczewski 您可以使用 [^a-z0-9] 再添加一个替代项
  • @KamilKiełczewski 然后添加另一个测试,例如 /^[0-9a-z]*$/.test(str)
【解决方案2】:

可以用一个正则表达式来实现:

let n=2,m=3; 
let s=["32abc","abc32","a3b2c","3abc2","a2","abcd23","a2b3c4","aa","32", "a3b_2c"];
let rx = new RegExp(
    "^" +                                         // Start of string
    "(?=(?:[^0-9]*[0-9]){0," + n + "}[^0-9]*$)" + // only 0 to n digits
    "(?=(?:[^a-z]*[a-z]){0," + m + "}[^a-z]*$)" + // only 0 to m letters
    "[a-z0-9]*" +                                 // only allow 0 or more letters/digits
    "$"                                           // End of string
);
let r=s.map(x=> rx.test(x));

console.log("current is:", JSON.stringify(r));
console.log("shoud be:   [true,true,true,true,true,false,false,true,true,false]");

请参阅regex demo

详情

  • ^ - 字符串开头
  • (?=(?:[^0-9]*[0-9]){0,2}[^0-9]*$) - 一个正向前瞻,它要求在当前位置的右侧紧接零到两次出现除数字之外的任何 0+ 字符,然后是一个数字,然后是除数字之外的 0+ 字符到末尾字符串的
  • (?=(?:[^a-z]*[a-z]){0,3}[^a-z]*$) - 一个正向前瞻,它要求在当前位置的右侧,除了小写 ASCII 字母和数字之外的任何 0+ 字符出现零到两次,然后是数字,然后是小写 ASCII 以外的 0+ 字符字符串末尾的字母
  • [a-z0-9]* - 0 个或多个小写 ASCII 字母或数字
  • $ - 字符串结束

【讨论】:

  • 这个解决方案的一个问题是像a3b_2c这样的字符串是有效的
  • @KamilKiełczewski 我之前写过:注意:如果您只想匹配由字母和数字组成的字符串,请在正则表达式模式的末尾添加[a-z0-9]*$。修改为仅匹配那些字符串。
  • 非常感谢:)
猜你喜欢
  • 2014-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多