Regex for at least 3 (numbers and special characters) in Android - java

I have a password rule that needs to satisfy those condition below:
At least 2 out of the following:
- At least 1 lowercase character
- At least 1 uppercase character
- At least 2 (numbers AND special characters)
I build my regex like this below:
String oneLowercaseCharacter = ".*[a-z].*";
String oneUppercaseCharacter = ".*[A-Z].*";
String oneNumber = ".*\\d.*";
String oneSpecialCharacter = ".*[^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
String threeNumbersAndCharacters = ".*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
And then I build the function like this below:
if ((Pattern.compile(oneLowercaseCharacter).matcher(s).find() && Pattern.compile(oneUppercaseCharacter).matcher(s).find())
|| (Pattern.compile(oneLowercaseCharacter).matcher(s).find()
&& Pattern.compile(oneSpecialCharacter).matcher(s).find()
&& Pattern.compile(oneNumber).matcher(s).find()
&& Pattern.compile(threeNumbersAndCharacters).matcher(s).find())
|| (Pattern.compile(oneUppercaseCharacter).matcher(s).find()
&& Pattern.compile(oneSpecialCharacter).matcher(s).find()
&& Pattern.compile(oneNumber).matcher(s).find()
&& Pattern.compile(threeNumbersAndCharacters).matcher(s).find())) {
//Do my stuff here
}
However, it does not work as expected. Not really sure why but if I test with different passwords, results show like this:
qwerty123 true (not expected)
qwerty!## false
qwerty12. true
Qwerty123 true
Qwerty12. true
Anyone has any idea where I missed?
Note: I search around stackoverflow already and look elsewhere already so that I came up with the above code, however could not go further.

The problem is in this line:
String oneSpecialCharacter = ".*[^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
The character ^ has a special meaning ("not") when it is used in the first position inside [].
This is why you need to escape it.
String oneSpecialCharacter = ".*[\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\#\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
Now your result should looks like this:
qwerty123 -> false
qwerty!## -> false
qwerty12. -> true
Qwerty123 -> true
Qwerty12. -> true
Other examples that emphasize the meaning of ^:
// the first character cannot be a
System.out.println(Pattern.compile("[^a]bc").matcher("abc").find()); // false
// the first character cannot be x, y or z, but it can be a
System.out.println(Pattern.compile("[^xyz]bc").matcher("abc").find()); // true
// the first character can be ^ or a
System.out.println(Pattern.compile("[\\^a]bc").matcher("abc").find()); // true
// the first character can be ^, x, y or z, but not a
System.out.println(Pattern.compile("[\\^xyz]bc").matcher("abc").find()); // false

Related

Regex contain only numbers and does not contain only 0

I would like to implement a regular expression that return true if:
The string contain only number
The string does not contain only 0 ( like 0000)
For example:
1230456 => true
888822200000 => true
00000000 => false
fff => false
I started to implement this
private static final String ARTICLE_VALID_FORMAT = "\\d";
private static final Pattern ARTICLE_VALID_FORMAT_PATTERN = Pattern.compile(ARTICLE_VALID_FORMAT);
private boolean isArticleHasValidFormat(String article) {
return StringUtils.isNotBlank(article) && ARTICLE_VALID_FORMAT_PATTERN.matcher(article).matches();
}
Now, it returns true if the article has only number. but i would like to test also if it is not all 0.
How to do that?
Thanks
You can use:
private static final String ARTICLE_VALID_FORMAT = "[0-9]*?[1-9][0-9]*";
which means:
Match zero or more digits; the ? means to match as few as possible before moving onto the next part
then one digit that's not a zero
then zero or more digits
Or, as Joachim Sauer suggested in comments:
private static final String ARTICLE_VALID_FORMAT = "0*[1-9][0-9]*";
which means:
Match zero or more zeros
then one digit that's not a zero
then zero or more digits
If you wanted to do it without regex, you could use (among many other ways):
string.chars().allMatch(c -> c >= '0' && c <= '9')
&& string.chars().anyMatch(c -> c != '0')
The regex pattern \d*[1-9]\d* as given by #AndyTurner is a good way to do this. Another approach would be to try to parse the string input to a long, and then check that it is greater than zero:
private boolean isArticleHasValidFormat(String article) {
try {
if (Long.parseLong(article) > 0) return true;
}
catch (NumberFormatException e) {
}
return false;
}
This solution assumes that you are only concerned with finding positive numbers. If not, and you want to cater to negatives, then check num != 0 instead.
Try this condition.
(Integer.pasrseInt("0" + article.replaceAll("^[0-9]", "0")) != 0) ? true : false
the ["0" +] is to avoid NumberFormatException for empty string
You don't need to make a Pattern object. Just call matches function from the String class
article.matches("\\d*[1-9]\\d*");
It's the same regex as Andy Turner suggested.

codingBat question: Returns true if for every '*' (star) in the string

i am working on this codingbat question:
Returns true if for every '*' (star) in the string, if there are chars both immediately before and after the star, they are the same.
Example:
sameStarChar("xy*yzz") → true
sameStarChar("xy*zzz") → false
sameStarChar("*xa*az") → true
My first attempt of code is :
public boolean sameStarChar(String str) {
//boolean flag = false;
for(int i =1;i< str.length()-1; i++){
if(str.charAt(i) == '*' && str.charAt(i-1) == str.charAt(i+1)){
return true;
}
}
return false;
}
and did not pass few case such: sameStarChar("12*2*3*") → false , sameStarChar("XYYYYYZ*") → false.
However, if changed the code to:
public boolean sameStarChar(String str) {
//boolean flag = false;
for(int i =1;i< str.length()-1; i++){
if(str.charAt(i) == '*' && str.charAt(i-1) != str.charAt(i+1)){
return false;
}
}
return true;
}
The result is corrected. I do not understand what is wrong with my first attempt.
In your second attempt you fixed the only problem you had with your code.
Your first attempt will be immediately terminate by returning true, if there is an * surrounded by matching chars. (Here you will miss out the upcoming *s with mismatching chars)
Your second case now will check whether your string contain an * which is surrounded by mismatching chars, and terminate it by returning false.
NOTE: This is an example where you align your checks to detect the negative scenario rather than traversing all and finding the positive ones.
In your case you can do two things (NOTE: we can safely remove the corner two, and you already done that),
Return true if : Every * in the string is surrounded by matching chars
OR
Return false if : There is at least one * which is surrounded by a mismatching chars.
Two issues with your first attempt:
It fails to consider the case of a string that doesn't contain any asterisks at all, for which the loop will run to completion and then false will incorrectly be returned.
It incorrectly returns true on the first pair of matched neighbours of an asterisk, regardless of any unmatched pairs that may follow.
In your first case, you are returning as soon as you find one valid match/occurrence which is wrong. Also, you are not checking for the cases where there are * at one or either ends.
In the second case, you are searching explicitly for mismatches. Also, the corner cases of * at ends naturally becomes a match/success.

Java Regex to Match a Number Within a Range

I'm trying to craft a Java regular expression to identify if a number (which I don't know until execution time) is within a range (and that range I also don't know until execution time).
Specifically, I'm trying to use Cisco's PRIME compliance module to validate my switch has no inactive VLANs (for this question, a VLAN is just a number), but PRIME uses Java regular expression syntax.
I know that the specific switch command I'm evaluating uses a syntax like:
switchport trunk allowed vlan 1,20,37,45,90-101,300-502,904-2044
How, then, can I tell if VLAN "x" is in any of those ranges?
If x = 20, it should match.
If x = 90, it should match.
If x = 900, it should fail.
If x = 1043, it should match.
Any ideas?
Edit: Unfortunately, the RegEx listed here is for ranges that are known; the examples are all hard-coded ranges. I need something that takes an unknown x, y, and z, where all x, y, and z might possibly be 1, 2, 3, or 4 digits, and matches if z is between x and y when written as "x-y".
Is there a way to take the string "x-y", parse it into \1 and \2 that are understood to be numbers, and match if (z >= \1 && z <= \2)?
I've tried looking at things like lookahead and lookbehind and crazy/obscure Java-compatible regex structures, but my head quickly got spun into the 4th dimension.
I don't think this should be done with a regular expression. Personally I'd use a regex to check if it's the right format, i.e. check if the string matches "VLAN ([0-9]+(-[0-9]+)?)(,([0-9]+(-[0-9]+)?))*", then split the latter part on the commas and use integer parsing from there, depending on if there is a '-' in there or not you can check the ranges.
For instance like this: https://jsfiddle.net/gcb9pm7f/15/
function testRanges()
{
var str = document.getElementById("textField").value;
var test = parseInt(document.getElementById("numberField").value);
str = str.toUpperCase(); // VLAN big
var regex = /^VLAN ([0-9]+(-[0-9]+)?)(,([0-9]+(-[0-9]+)?))*$/g;
if (regex.test(str))
{
str = str.substring(5, str.length); // remove 'VLAN'
var splitArray = str.split(',');
for (var idx = 0; idx < splitArray.length; idx++)
{
var rangeStr = splitArray[idx];
if (rangeStr.includes('-'))
{
// range, check both values.
var a = parseInt(rangeStr.split('-')[0]);
var b = parseInt(rangeStr.split('-')[1]);
if (a > b)
{
if (test >= b && test <= a) return true; // range is inclusive
}
else // a <= b
{
if (test <= b && test >= a) return true; // range is inclusive
}
}
else // not a range, single value
{
if (parseInt(rangeStr) === test) return true;
}
}
}
return false; // no match or regex not matching.
}
Adjust to your programming language as needed. Should be fairly straight forward.

Java - using ".contains" in the opposite manner

I want to be able to print a string that doesn't contain the words "Java", "Code" or "String", though I am unsure on how to achieve this as I thought this would be achieved by using '!' (NOT). However, this is not the case as the string is still printed despite the inclusion of the words I want to forbid.
Any advice on how to achieve this would be greatly appreciated, thanks in advance.
System.out.println("Type in an input, plez?");
String userInput6 = inputScanner.nextLine();
if (!userInput6.toLowerCase().contains("Java") || !userInput6.toLowerCase().contains("Code") || !userInput6.toLowerCase().contains("String")) {
System.out.println("I see your does not string contain 'Java', 'Code' or 'String, here is your string:- " + userInput6);
} else {
System.out.println("Your string contains 'Java, 'Code' or 'String'.");
}
I thought this would be achieved by using '!' (NOT)
It is. You just haven't applied it correctly to your situation:
You start with this statement:
userInput6.toLowerCase().contains("java") ||
userInput6.toLowerCase().contains("code") ||
userInput6.toLowerCase().contains("string")
which checks if the input contains any of these, and you wish to negate this statement.
You can either wrap the entire statement in parentheses (()) and negate that:
!(userInput6.toLowerCase().contains("java") ||
userInput6.toLowerCase().contains("code") ||
userInput6.toLowerCase().contains("string"))
or apply the DeMorgan's law for the negation of disjunctions which states that the negation of a || b is !a && !b.
So, as Carcigenicate stated in the comments, you would need
!userInput6.toLowerCase().contains("java") &&
!userInput6.toLowerCase().contains("code") &&
!userInput6.toLowerCase().contains("string")
instead.
Your statement is simply checking if the string doesn't contain at least one of these substrings. This means the check would only fail if the string contained all of these strings. With ||, if any operand is true, the entire statement is true.
Additionally, mkobit makes the point that your strings you are checking for should be entirely lowercase. Otherwise, you are checking if a .toLowerCased string contains an uppercase character - which is always false.
An easier way to think of it may be to invert your if statement:
if (userInput6.toLowerCase().contains("Java") ||
userInput6.toLowerCase().contains("Code") ||
userInput6.toLowerCase().contains("String")) {
System.out.println("Your string contains 'Java, 'Code' or 'String'.");
} else {
System.out.println("I see your does not string contain 'Java', 'Code' or 'String, here is your string:- " + userInput6);
}
Since you're using logical OR, as soon as one your contains checks it true, the entire condition is true. You want all the checks to be true, so you need to use logical AND (&&) instead
As #mk points out, you have another problem. Look at:
userInput6.toLowerCase().contains("Java")
You lower case the string, then check it against a string that contains an uppercase. You just removed all uppercase though, so that check will always fail.
Also, you can use regexp :)
boolean notContains(String in) {
return !Pattern.compile(".*((java)|(code)|(string)).*")
.matcher(in.toLowerCase())
.matches();
}
Or just inline it:
System.out.println("Type in an input, plez?");
String userInput6 = inputScanner.nextLine();
if (!Pattern.compile(".*((java)|(code)|(string)).*")
.matcher(userInput6.toLowerCase())
.matches()) {
System.out.println("I see your does not string contain 'Java', 'Code' or 'String, here is your string:- " + userInput6);
} else {
System.out.println("Your string contains 'Java, 'Code' or 'String'.");
}

What does this Java 8 stream code mean?

boolean isA2Z(String str) {
return (str.chars().filter(i -> i >= 'a' && i <= 'z').distinct().count() == 26);
}
From the method name, it looks like it tests whether a String contains letters from a->z, but it doesn't look right?
It collects individual characters from the string and then return the count of the stream. How can this work?
str.chars() --> returns IntStream for characters in String
filter(i -> i >= 'a' && i <= 'z') --> Filtering and it allows only [a, z] (inclusive) to go on next processing function
distinct() --> get all distinct values
count() --> count the items made their way through here.
functionally it checks if the String contains all the small [a, z] (inclusive) atleast once. (avoiding corner cases here)
Here's how it works, step by step:
Convert string to list of individual characters
Exclude any characters not between 'a' and 'z' (inclusive)
Create a unique list of remaining characters
Count the number of unique characters
Return true if the number is 26; return false otherwise
In other words, the method returns true if and only if the input string contains at least one occurrence of every lowercase letter from a to z.
Lets say if string is following
"abbcdefghijklmnopqrstuvwxyz"
This method will return true. Method is checking whether string contain all alphabets from a to z regardless if they are repeating.

Categories