正则表达式必须在长度范围内,并包含字母和数字。

3
我想编写一个正则表达式,它可以查找长度为10-15的子字符串,其中所有字符都是[A-Z0-9]并且它必须包含至少1个字母和1个数字(空格可以,但不要出现其他特殊字符)。一些例子:
  • ABABABABAB12345 应该匹配
  • ABAB1234ABA32 应该匹配
  • ABA BA BABAB12345 应该匹配
  • 1234567890987 不应该匹配
  • ABCDEFGHIJK 不应该匹配
  • ABABAB%ABAB12?345 不应该匹配

到目前为止,我想到的最好的两个候选项是:

  1. (?![A-Z]{10,15}|[0-9]{10,15})[0-9A-Z]{10,15} - 如果字符串有10个连续的数字/字母,则此方法会失败,即使15个字符的字符串具有混合性(例如 ABABABABAB12345)。
  2. (?=.*[0-9])(?=.*[A-Z])([A-Z0-9]+){10,15 } - 如果后面还有数字,则此方法将匹配15个连续字母,反之亦然(例如123456789098765 abcde将匹配123456789098765)。

(我需要在 Python 和 JS 中实现此功能)


所以必须包含至少一个数字和一个字母吗? - depperm
1
ABCDEFGHIJK matches the requirements, why do you say it should not match? Same with 1234567890987 - smac89
你要查找的字符串是单独存在于一行中吗?还是你想在像“The quick brown fox jumped over the ABABABABAB12345 dog”这样的句子中查找“ABABABABAB12345”? - user12842282
如所述,您似乎只需要 ^[A-Z0-9 ]{15,20}$,但我猜测您可能有其他未明确说明的要求。请在上面的评论中回答问题(通过编辑)。不要使用“...其中所有字符都是[A-Z0-9](空格可以,但不包括其他特殊字符)。”而是说“其中所有字符都是[A-Z0-9 ]”(或“其中所有允许的字符都在字符类[A-Z0-9 ]中”)。 - Cary Swoveland
抱歉!在一天结束时写下的问题 - 错过了非常关键的一点,即必须包含至少1个字母和1个数字。 - Toby S
3个回答

1
这不包括ABA BA BABAB12345,但这仍然可能有所帮助。
根据您要匹配的内容,看起来您想要混合使用字母和数字。
您可以使用两个前瞻。一个在接下来的15个字符中查找字母,另一个在相同位置查找字母。如果匹配,则查找长度为10到15的数字和字母组合。

(?=.{0,14}\d)(?=.{0,14}[A-Z])[A-Z\d]{10,15}

https://regex101.com/r/qw1Q0S/1

(?=.{0,14}\d) 第1到15个字符必须是数字

(?=.{0,14}[A-Z]) 第1到15个字符必须是大写字母

[A-Z\d]{10,15} 如果前面的条件成立,匹配10到15个字母和数字

使用 改进的答案 进行编辑:

为了考虑空格,你可以对上述概念进行调整。

(?=(?:. *+){0,14}\d)(?=(?:. *+){0,14}[A-Z])(?:[A-Z\d] *){10,15}

上面,在前瞻中我们匹配了 .{0,14}。现在已将 . 改为了 (?:. *+),这是一个非捕获组,除了匹配 .,还匹配0个或多个空格。

因此,将它们放在一起:

前瞻 1:

(?=(?:. *+){0,14}\d)

这个匹配模式可以匹配0到14个字符,它们之间可能有空格。它会忽略空格,并使用占有量词(*+)来匹配空格,以防止引擎在匹配空格时回溯。如果没有+修饰符,该模式仍然有效,但是匹配所需的步骤将增加一倍以上。
先行断言2: (?=(?:. *+){0,14}[A-Z]) 与先行断言1相同,但现在测试的是大写字母而不是数字。
如果先行断言1和先行断言2都匹配成功,则引擎将停留在一个我们可以进行匹配的位置。
实际匹配: (?:[A-Z\d] *){10,15} 这个模式可以匹配大写字母和数字,还可以匹配0或多个空格。唯一的缺点是尾随空格将包含在您的匹配中,但这在后处理中很容易处理。
编辑:

所有空格(\r\n\t )都可以通过使用\s 相对应来解释

根据存在的空间量,必须使用占有量词来防止灾难性回溯。使用占有量词修改输入后,完成步骤为22,332步,而使用相同输入但使用常规量词则无法匹配任何内容,因为会产生灾难性回溯

值得注意的是,占有量词*+不受JavaScript或Python内置的re模块支持,但它受Python的regex模块支持:

>>> import regex
>>> pattern = r'(?=(?:.\s*+){0,14}\d)(?=(?:.\s*+){0,14}[A-Z])(?:[A-Z\d]\s*){10,15}'
>>> regex.search(pattern, 'AAAAAAAAAA\n2')
<regex.Match object; span=(0, 12), match='AAAAAAAAAA\n2'>
>>> 


非常有用 - 涵盖了我需要的90%。谢谢! - Toby S
我已更新答案。我想出了一种解决空格的方法。 - user12842282
我在使用“+”时遇到了“前面的标记无法量化”的错误。另一个特殊情况是,在10和14之间有换行符,例如“AAAAAAAAAA\n2”将匹配“AAAAAAAAAA”。 - Toby S
很遗憾,JavaScript不支持该功能。使用带有“regex”(第三方模块)的Python是否可行? - user12842282

1

如果每个字符串都在自己的一行上,那么您可以使用起始/结束锚点构建正则表达式:

  • ^(?=.*[0-9])(?=.*[A-Z])(?:\s*[A-Z0-9]\s*){10,15}$
    • ^ - 行首
      • (?=.*[0-9]) - 向前查找,必须包含数字
      • (?=.*[A-Z]) - 向前查找,必须包含字母
      • (?: - 开始一个非捕获组
        • \s*[A-Z0-9]\s* 包含一个带有可选空格的字母或数字
      • ) - 结束非捕获组
      • {10,15} - 模式出现10到15次
    • $ - 行尾

在此处查看实时示例:https://regex101.com/r/eWX2Qo/1


每个字符串不是独立的一行 - 明确地说,我想匹配的每个示例都是较长字符串中的子字符串。它可能在自己的一行上,但也可能不在。 - Toby S

0

有实力

function lfunko() {
  let a = ["ABABABABAB12345","ABAB1234ABA32","ABA  BA BABAB12345","1234567890987","ABCDEFGHIJK","ABABAB%ABAB12?345"];
  let o = a.map((s,i) => {
    let ll = s.split("").filter(s => s.match(/[A-Z]/)).length;
    let ln = s.split("").filter(s => s.match(/[0-9]/)).length;
    let ot = s.split("").filter(s => s.match(/[^A-Z0-9]/)).length;
    let sum = ll + ln
    return (ll > 1 && ln > 1 && sum > 9 && sum < 16 && ot == 0)? `${s} - TRUE`:`${s} - FALSE`;
  });
  console.log(JSON.stringify(o));

    }
    
Execution log
11:18:20 PM Notice  Execution started
11:18:21 PM Info    ["ABABABABAB12345 - TRUE","ABAB1234ABA32 - TRUE","ABA  BA BABAB12345 - FALSE","1234567890987 - FALSE","ABCDEFGHIJK - FALSE","ABABAB%ABAB12?345 - FALSE"]
11:18:21 PM Notice  Execution completed

您的[A-Z0-9]需求不包括空格,因此第三个示例应为false。

应该是

  • ABABABABAB12345 应匹配
  • ABAB1234ABA32 应匹配
  • ABA BA BABAB12345 不应匹配,因为有空格
  • 1234567890987 不应匹配
  • ABCDEFGHIJK 不应匹配
  • ABABAB%ABAB12?345 不应匹配

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