如何在字符串中匹配非单词字符?

huangapple go评论19阅读模式
英文:

How do I match non-word characters anywhere in the string?

问题

这是一个简单的问题,请听我解释一下 - 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("密码需要在6到10个字符之间");
    }
    else if(password.matches("\\W")) // 这应该在输入为 MyPass123# 时匹配
    {
        System.out.printf("密码必须只包含字母和数字");
    }
    else if(!password.matches(".*(\\d).*(\\d).*"))
    {
        System.out.printf("密码需要至少包含2个数字");
    }
    else
    {
        System.out.printf("密码有效");
    }
}
英文:

This is a simple question, but please hear me out - A part of a homework assignment for Java has a password validator method. The requirements are simple - password must be between 6-10 characters, must be made only of digits or letters and has to have at least 2 digits in it to be valid. I made this with if statements and using regex, for some reason I cannot get the non-word character regex to match despite every online regex checker showing this should work and even the jetbrains plugin for regex check shows this should be valid. (I also understand this could be done with a one-liner and none of the if statements but this way is simpler for me.

Example input - MyPass123 should be valid, MyPass123# should match the non-word character and should return "Password must consist only of letters and digits" instead this never happens. I am a beginner in Java so it is most likely I am not doing something right even though it is such a simple problem. Thank you in advance!

Method code below:

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

答案1

得分: 2

只有在字符串由单个非字母数字字符组成时才匹配(= [^a-zA-Z0-9_])。

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

英文:

You're only matching if the string consists of a single character which is non alphanumeric (= [^a-zA-Z0-9_]).

If you want any string which contains at least one non alphanumeric character: .*?\W.*

答案2

得分: 2

String#matches 总是执行完全匹配,即匹配需要跨越整个字符串,从第一个字符到最后一个字符。要在字符串的任何位置搜索匹配项,您需要使用Matcher对象的find方法

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

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

英文:

String#matches always performs a whole match, i.e. the match needs to span the whole string from the first to the last character. To search for a match anywhere in the string, you need to use the find method of a Matcher object instead:

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

You will need to do the same with your other regular expressions.

答案3

得分: 1

我已测试下面的代码。有两种选择,尝试使用Konrad在上面的评论中提到的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("密码长度必须在6到10个字符之间");
        }
        else if(!Pattern.matches("\\w{6,10}",password)) //当输入为MyPass123#时应匹配
        {
            System.out.println("密码必须仅包含字母和数字");
        }
        else if(!Pattern.matches(".*?\\d{2,}.*?",password))
        {
            System.out.println("密码必须至少包含2个数字");
        }
        else
        {
            System.out.println("密码有效");
        }
    }
    public static void main(String[] args) 
    {
        passswordCheck("Mypass2");
    }
}
英文:

I have tested the below code. Two options are possible, try using the find method as mentioned by Konrad in one of the comments above or handle it in the regex to match a character anywhere in the string.

\\w{6,10} - Matches only the valid passwords which contains word character(A-Za-z0-9)

.*?\\d{2,}.*? - Looks for 2 or more consecutive digits

I have changed it to use Pattern.matches.

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

答案4

得分: 0

以下是翻译好的部分:

  1. 你使用了\W(即[^\w]),它匹配非单词字符,但请注意\w不仅匹配数字和字母,还匹配下划线 _,而在有效密码中不需要下划线。因此,你需要使用\p{Alnum}。或者,你可以使用[A-Za-z0-9]。另外,为了考虑整个字符串,需要使用量词 +

  2. 模式\d.*\d匹配两个数字之间的字符串,这两个数字可以出现在密码的任何位置(不仅仅是在开头和结尾),因此你需要匹配任何位置,而不是整个字符串。你可以从这个示例中了解这一点。因此,应该使用Matcher#find而不是String#match。请注意,在你的正则表达式模式中不需要括号 ( ) 来表示捕获组,因为这不符合你的需求。

给出的示例代码解决了所有这些问题:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        // 测试字符串
        String[] arr = { "abcdefghjk", "abc1def2gh", "Ab1Cd2EfGh", "Ab1CdEfGhI", "Ab1Cd2E3Gh", "Ab_ed2EFG3" };
        for (String s : arr) {
            System.out.println("验证密码," + s);
            passswordCheck(s);
        }
    }

    public static void passswordCheck(String password) {
        if (password.length() < 6 || password.length() > 10) {
            System.out.println("密码需要在6到10个字符之间。\n");
        } else if (!password.matches("\\p{Alnum}+")) {
            System.out.println("密码必须只包含字母和数字。\n");
        } else {
            Pattern pattern = Pattern.compile("\\d.*\\d");
            Matcher matcher = pattern.matcher(password);
            if (!matcher.find()) {
                System.out.println("密码需要至少包含2个数字。\n");
            } else {
                System.out.println("密码有效\n");
            }
        }
    }
}

输出:

验证密码,abcdefghjk
密码需要至少包含2个数字。

验证密码,abc1def2gh
密码有效

验证密码,Ab1Cd2EfGh
密码有效

验证密码,Ab1CdEfGhI
密码需要至少包含2个数字。

验证密码,Ab1Cd2E3Gh
密码有效

验证密码,Ab_ed2EFG3
密码必须只包含字母和数字。
英文:

Problems in your code:

  1. You have used \W (i.e. [^\w]) which matches non-word character but note that \w matches not only digits and alphabets but also _ which you do not need in the valid password. Therefore, you need to use \p{Alnum}. Alternatively, you can use [A-Za-z0-9]. Also, in order to consider the whole string, the quantifier + is required.
  2. The pattern, \d.*\d matches the string bounded by two digits which can be at any place (i.e. not just at the beginning and at the end) in the password and therefore, you need to match any place, not the whole string. You can understand it from this example. Thus, String#match will be able to match the whole string only when the digits are placed in the beginning and at the end. Therefore, you need to use Matcher#find instead of String#match. Note that you do not need parenthesis ( ) around \d in your regex pattern. The parenthesis ( ) is used to specify capturing group which you do not need for your requirement.

Given below is a demo code addressing all these issues:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
	public static void main(String[] args) {
		// Test strings
		String[] arr = { &quot;abcdefghjk&quot;, &quot;abc1def2gh&quot;, &quot;Ab1Cd2EfGh&quot;, &quot;Ab1CdEfGhI&quot;, &quot;Ab1Cd2E3Gh&quot;, &quot;Ab_ed2EFG3&quot; };
		for (String s : arr) {
			System.out.println(&quot;Validating the password, &quot; + s);
			passswordCheck(s);
		}
	}

	public static void passswordCheck(String password) {
		if (password.length() &lt; 6 || password.length() &gt; 10) {
			System.out.println(&quot;Password needs to be between 6 and 10 characters.\n&quot;);
		} else if (!password.matches(&quot;\\p{Alnum}+&quot;)) {
			System.out.println(&quot;Password must consist only of letters and digits.\n&quot;);
		} else {
			Pattern pattern = Pattern.compile(&quot;\\d.*\\d&quot;);
			Matcher matcher = pattern.matcher(password);
			if (!matcher.find()) {
				System.out.println(&quot;Password needs to have at least 2 digits.\n&quot;);
			} else {
				System.out.println(&quot;Password is valid\n&quot;);
			}
		}
	}
}

Output:

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.

huangapple
  • 本文由 发表于 2020年7月30日 15:30:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/63168229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定