【问题标题】:How do I match non-word characters anywhere in the string?如何匹配字符串中任何位置的非单词字符?
【发布时间】:2020-07-30 07:30:06
【问题描述】:

这是一个简单的问题,但请听我说 - Java 家庭作业的一部分有一个密码验证器方法。要求很简单 - 密码必须介于 6-10 个字符之间,只能由数字或字母组成,并且必须至少包含 2 位数字才有效。我使用 if 语句并使用正则表达式进行了此操作,由于某种原因,我无法让非单词字符正则表达式匹配,尽管每个在线正则表达式检查器都显示这应该可以工作,甚至用于正则表达式检查的 jetbrains 插件也显示这应该是有效的。 (我也明白这可以用单行语句来完成,没有 if 语句,但这种方式对我来说更简单。

示例输入 - MyPass123 应该是有效的,MyPass123# 应该匹配非单词字符并且应该返回“密码必须仅由字母和数字组成”,而这永远不会发生。我是 Java 的初学者,所以即使这是一个如此简单的问题,我也很可能没有做正确的事情。提前谢谢!

方法代码如下:

public static void passswordCheck(String password)
    {
        if(password.length()<6 || password.length()>10)
        {
            System.out.printf("Password needs to be between 6 and 10 characters");
        }
        else if(password.matches("\\W")) \\This should match when input is MyPass123#
        {
            System.out.printf("Password must consist only of letters and digits");
        }
        else if(!password.matches("/(\\d).*(\\d)/"))
        {
            System.out.printf("Password needs to have at least 2 digits");
        }
        else
        {
            System.out.printf("Password is valid");
        }
    }

【问题讨论】:

    标签: java regex


    【解决方案1】:

    String#matches 总是执行整个匹配,即匹配需要跨越从第一个字符到最后一个字符的整个字符串。要在字符串中搜索匹配任何地方,您需要改用Matcher 对象的find method

    final Pattern nonWordChar = Pattern.compile("\\W");
    if (nonWordChar.matcher(password).find()) {
        System.out.printf("Password must consist only of letters and digits");
    }
    …
    

    您需要对其他正则表达式执行相同操作。

    【讨论】:

      【解决方案2】:

      只有当字符串包含一个非字母数字的单个字符(= [^a-zA-Z0-9_])时,您才匹配。

      如果您想要任何包含至少一个非字母数字字符的字符串:.*?\W.*

      【讨论】:

      • 谢谢,这对我有帮助,这是我的一个错误,因为我错过了应该在表达式的开头和结尾添加 .* 的事实
      【解决方案3】:

      我已经测试了下面的代码。有两种选择,尝试使用 Konrad 在上述任一 cmets 中提到的 find 方法,或在正则表达式中处理它以匹配字符串中任意位置的字符。

      \\w{6,10} - 仅匹配包含单词字符的有效密码(A-Za-z0-9)

      .*?\\d{2,}.*? - 查找 2 个或更多连续数字

      我已将其更改为使用 Pattern.matches。

      import java.util.regex.*;
      public class test {
          public static void passswordCheck(String password)
          {
              if(password.length()<6 || password.length()>10)
              {
                  System.out.println("Password needs to be between 6 and 10 characters");
              }
              else if(!Pattern.matches("\\w{6,10}",password)) //This should match when input is MyPass123#
              {
                  System.out.println("Password must consist only of letters and digits");
              }
              else if(!Pattern.matches(".*?\\d{2,}.*?",password))
              {
                  System.out.println("Password needs to have at least 2 digits");
              }
              else
              {
                  System.out.println("Password is valid");
              }
          }
          public static void main(String[] args) 
          {
              passswordCheck("Mypass2");
          }
      }
      

      【讨论】:

      • 谢谢,我的问题表述不正确 - 要求密码必须包含 2 位数字,但您的建议让我想到了正确的方向!
      【解决方案4】:

      代码中的问题:

      1. 您使用了匹配非单词字符的\W(即[^\w]),但请注意\w 不仅匹配数字和字母,还匹配有效密码中不需要的_。因此,您需要使用\p{Alnum}。或者,您可以使用[A-Za-z0-9]。此外,为了考虑整个字符串,quantifier+ 是必需的。
      2. 模式 \d.*\d 匹配由两位数字限定的字符串,该字符串可以位于密码中的任何位置(即不仅仅是开头和结尾),因此,您需要匹配任何位置,而不是整个细绳。您可以从this example 了解它。因此,String#match 只有在数字位于开头和结尾时才能匹配整个字符串。因此,您需要使用Matcher#find 而不是String#match。请注意,在您的正则表达式模式中,您不需要在 \d 周围加上括号 ( )。括号( ) 用于指定您不需要的capturing group

      以下是解决所有这些问题的演示代码:

      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      public class Main {
          public static void main(String[] args) {
              // Test strings
              String[] arr = { "abcdefghjk", "abc1def2gh", "Ab1Cd2EfGh", "Ab1CdEfGhI", "Ab1Cd2E3Gh", "Ab_ed2EFG3" };
              for (String s : arr) {
                  System.out.println("Validating the password, " + s);
                  passswordCheck(s);
              }
          }
      
          public static void passswordCheck(String password) {
              if (password.length() < 6 || password.length() > 10) {
                  System.out.println("Password needs to be between 6 and 10 characters.\n");
              } else if (!password.matches("\\p{Alnum}+")) {
                  System.out.println("Password must consist only of letters and digits.\n");
              } else {
                  Pattern pattern = Pattern.compile("\\d.*\\d");
                  Matcher matcher = pattern.matcher(password);
                  if (!matcher.find()) {
                      System.out.println("Password needs to have at least 2 digits.\n");
                  } else {
                      System.out.println("Password is valid\n");
                  }
              }
          }
      }
      

      输出:

      Validating the password, abcdefghjk
      Password needs to have at least 2 digits.
      
      Validating the password, abc1def2gh
      Password is valid
      
      Validating the password, Ab1Cd2EfGh
      Password is valid
      
      Validating the password, Ab1CdEfGhI
      Password needs to have at least 2 digits.
      
      Validating the password, Ab1Cd2E3Gh
      Password is valid
      
      Validating the password, Ab_ed2EFG3
      Password must consist only of letters and digits.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-22
        相关资源
        最近更新 更多