【问题标题】:regex detect word with 2+ number and 2+ character正则表达式检测带有 2+ 数字和 2+ 字符的单词
【发布时间】:2019-05-16 17:15:40
【问题描述】:

我需要一个正则表达式来检测长度为 8 个字符且包含 2 个以上数字和 2 个以上字符(无特殊字符)的单词。

我接近解决方案,我在 regex101.com 上做了正则表达式。

问题是包含一个数字的单词不应该与我的正则表达式相关。

我用(?![A-Za-z]{7,}) 丢弃了所有包含最少 7 个字符的单词。

我用(?![\d]{7,})丢弃了所有包含最少7个数字的数字。

并且我丢弃了包含最少 2 个数字和 2 个字符 (?=[a-zA-Z\d]{2})[A-Za-z\d]{8} 的单词。

为什么匹配vaff8loe

我创建了这个正则表达式,因为在我用 ******* 替换整个单词之后。 喜欢:

papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y

替换后("regex","********")

********ciao il mio pin papaver1 è reeredji332ji con ******** 1234567o ******** papavero 9o ********

【问题讨论】:

标签: javascript java regex replace regex-group


【解决方案1】:

使用 2 个零宽度正向预测:

(?=.*?[a-zA-Z].*?[a-zA-Z])    Must contain 2 ASCII letters
(?=.*?[0-9].*?[0-9])          Must contain 2 digits
[a-zA-Z0-9]{8}                Must be exactly 8 letters and/or digits

如果不使用matches() 运行正则表达式,请添加^$

这意味着一个完整的正则表达式:

^(?=.*?[a-zA-Z].*?[a-zA-Z])(?=.*?[0-9].*?[0-9])[a-zA-Z0-9]{8}$

为获得最佳性能,请将. 模式替换为负字符类。在这种情况下,您可能希望使用重复的非捕获组来缩短它:

(?=(?:[^a-zA-Z]*[a-zA-Z]){2})
(?=(?:[^0-9]*[0-9]){2})

更新

由于问题已更新为需要正则表达式来用 * 替换此类单词,^$ 锚点应更改为 \b 单词边界模式,并且必须更改否定字符类只跳过有效字符:

s = s.replaceAll("\\b(?=(?:[0-9]*[a-zA-Z]){2})(?=(?:[a-zA-Z]*[0-9]){2})[a-zA-Z0-9]{8}\\b", "********");

请参阅regex101 进行演示。

请注意,给定示例中的vaff8loe 仅包含 1 个数字,因此不应替换。

【讨论】:

  • 你是如何丢弃_的?
  • 我需要一个正则表达式/模式来替换为 *
  • @MirkoCianfarani 抱歉,我不明白。正则表达式只会匹配正好 8 个字母和/或数字的字符串 ([a-zA-Z0-9]{8}),因此它不允许使用下划线。没有什么可以丢弃的。
  • @MirkoCianfarani 抱歉,我不明白。这个问题没有提到 replace 任何东西,只是关于 detecting 一些东西。
  • 当然,这是我的错,因为之后我注意到正则表达式不适用于我的情况:/ .. 抱歉,这是我的经验不足
【解决方案2】:

在需要对解析应用这么多条件的情况下(单词必须有长度 == 8、2+ 字母字符、2+ 数字字符且没有特殊字符),我认为你应该努力寻求解决方案 read 而不是将所有内容都放在一个复杂的正则表达式中。

假设您使用@Andreas 解决方案,您的代码将如下所示:

let s = "papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y";

s = s.replace(/\b(?=(?:[0-9]*[a-zA-Z]){2})(?=(?:[a-zA-Z]*[0-9]){2})[a-zA-Z0-9]{8}\b/g, "********");

console.log(s);

目前尚不清楚您在这里做什么,最终的错误和/或对您的逻辑的更改将难以维护。相反,您可以利用function replacement parameter 来打破您的规则。然后你会有这样的东西:

let s = "papave23 ciao il mio pin papaver1 è reeredji332ji con vaff8loe 1234567o 123t123t papavero 9o 123t123y";

// The first regex filters only 8-length words
s = s.replace(/\b\w{8}\b/g, 
    function(fullMatch) {
      // .match() can return null if no match is found, 
      // so I'm accounting for this.
      const digitMatch = fullMatch.match(/\d/g) || [];
      const letterMatch = fullMatch.match(/[a-zA-Z]/g) || [];
      const specialCharMatch = fullMatch.match(/\[^a-zA-Z0-9]/g);

      if (digitMatch.length >= 2
       && letterMatch.length >= 2
       && specialCharMatch === null) {
        return "********";
       } else {
        return fullMatch;
       }
  });

console.log(s);

它更冗长,但也更具可读性和可调试性。

希望对你有帮助!

【讨论】:

    【解决方案3】:

    您可以使用正向前瞻模式来限制数字和字母的数量:

    \b(?=(?:\w*\d){2}\w*)(?=(?:\w*[A-Za-z]){2}\w*)\w{8}\b
    

    演示:https://regex101.com/r/z33bUv/7

    【讨论】:

    • \w 也允许_ 下划线,根据问题是不允许的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多