Regular Expression Matching for number only with 2 digits repeated - java

I am trying to match number which are having 2 digits and those are repeated and the length of number is 7 digits .
I want to match these numbers from java .
example numbers:
3433434
6776767
9000999
Please help to create the regular expression for these pattern numbers

I'd recommend hiding any regexes inside helper methods:
private static boolean matchesCriteria(String s) {
return exactlySevenDigits(s) && containsRepeatedDigits(s);
}
private static boolean exactlySevenDigits(String s) {
return s.matches("\\d{7}");
}
private static boolean containsRepeatedDigits(String s) {
return s.matches(".*(\\d)\\1.*");
}
Example results:
3433434 true
6776767 true
9000999 true
1234567 false (no repeating numbers)
12331233 false (too long)
123356A false (not all digits)

You can do it as follows:
String str = "3433434";
boolean sevenOf2Digits = str.length() == 7 &&
str.matches("(\\d)\\1*+(\\d)(\\1|\\2)*");
System.out.println(sevenOf2Digits);
The first (\\d) captures the first digit in group 1.
\\1 is a backreference to group 1, so the first digit. * is 0 or more of those digits, + makes that possessive, which is required to prevent the next (\\d) from matching the same digit.
The following (\\d) captures the second digit in group 2.
(\\1|\\2)* just matches 0 or more of any combination of the first or second digits.
I separated out the length check for simplicity. If you want a pure regex solution, you can add the length check to your regex in the form of a lookahead by adding (?=.{7}$) to the start of your regex.
"(?=.{7}$)(\\d)\\1*+(\\d)(\\1|\\2)*"

With regex it is a little complicated, I would use this way (Java 8+) instead :
boolean check = myString.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.toSet())
.size() == 2;
The idea is to create a Set with the character of this string, if the size of the Set is 2 then it is correct String else it is not.
Or as Ralf Renz mention in comment, you can use this short way :
boolean check = myString.chars().distinct().count() == 2;
So your final solution should look like this :
boolean check = myString.matches("\\d{7}") && myString.chars().distinct().count() == 2;

(?=^.{7}$)(\d)\1*(?!\1)(\d)(?:\1|\2)*
This should do it. It finds a digit and repeats, then finds a second digit and repeats. Then it checks if the rest of the number is one of those 2.
I'll explain in detail what this does.
(?=^.{7}$): Before starting, make sure there are 7 characters between the start and end. If shorter or longer, fast fails.
(\d)\1*(?!\1)(\d): Get the first digit and save it in a capture group. Then matches if the captured digit is also the next one. If there is only a single digit, the next part will catch that. Last digit should always be different then the first one.
(?:\1|\2): repeat the 2 captured digits 0 or more times.

String regex = "[10]{7}|[20]{7}|[21]{7}|[30]{7}|[31]{7}|[32]{7}|[40]{7}|[41]{7}|[42]{7}|[43]{7}|[50]{7}|[51]{7}|[52]{7}|[53]{7}|[54]{7}|[60]{7}|[61]{7}|[62]{7}|[63]{7}|[64]{7}|[65]{7}|[70]{7}|[71]{7}|[72]{7}|[73]{7}|[74]{7}|[75]{7}|[76]{7}|[80]{7}|[81]{7}|[82]{7}|[83]{7}|[84]{7}|[85]{7}|[86]{7}|[87]{7}|[90]{7}|[91]{7}|[92]{7}|[93]{7}|[94]{7}|[95]{7}|[96]{7}|[97]{7}|[98]{7}";
System.out.println(Pattern.matches(regex, "3433434"));
System.out.println(Pattern.matches(regex, "6776767"));
System.out.println(Pattern.matches(regex, "9000999"));
That should do it. All combinations of two digits with a length of 7.

Related

3 out of 4 conditions in regex java [duplicate]

This question already has answers here:
The best way to match at least three out of four regex requirements
(2 answers)
Closed 2 years ago.
I am trying to create a java to check strength of a password with regex. The password must pass 3 out of 4 conditions:
lowercase
uppercase
contains digits
has special characters
The code looks like below:
import java.util.*;
public class StringPasswordStrength {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter password: ");
String password = input.nextLine();
boolean test = checkStrength(password);
if (test) {
System.out.print("OK");
}
else {
System.out.print("Not strong enough!");
}
}
public static boolean checkStrength(String password) {
if (password.matches("^(?=.*[a-zA-Z][0-9][!##$%^&*])(?=.{8,})")){
return true;
}
else {
return false;
}
}
}
However when the password is Passw0rd it doesn't accept. How can I change the conditions in regex that the program would accept Passw0rd because it passes 3 out of 4 conditions: uppercase, lowercase and digit?
I would suggest avoiding a potentially cryptic regular expression for this, and instead to provide something easier to read, understand and maintain (albeit more verbose).
Something like this (depending on what your conditions are, of course). For example, a length test should be mandatory:
public boolean isValid(String password) {
// password must contain 3 out of 4 of lowercase, uppercase, digits,
// and others (punctuation, symbols, spaces, etc.).
if (password == null) {
return false;
}
if (password.length() < 8) {
return false;
}
char[] chars = password.toCharArray();
int lowers = 0;
int uppers = 0;
int digits = 0;
int others = 0;
for (Character c : chars) {
if (Character.isLowerCase(c)) {
lowers = 1;
} else if (Character.isUpperCase(c)) {
uppers = 1;
} else if (Character.isDigit(c)) {
digits = 1;
} else {
others = 1;
}
}
// at least 3 out of 4 tests must pass:
return (lowers + uppers + digits + others >= 3);
}
I understand this is not a direct answer to your question, and so may not meet your needs.
I am also deliberately avoiding the discussion about char[] vs. String for password handling in Java - for example, see this post.
EDIT: Removed wording relating to password length, and changed related code to reflect the question.
You could define a set of rules (regex), count how many a given password comply with and compare with the minimum you require. A possible implementation could be:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* Patterns to be tested in your passwords. If you want some of them
* mandatory, you can define them in a "mandatoryPatterns" list and
* check those ones always.
*/
static List<String> patterns = Arrays.asList(
".*[A-Z]+.*",
".*[a-z]+.*"
);
/** Number of required patterns. */
static long requiredPatterns = 1;
/** This functions counts the number of patterns that a password matches. */
static long passwordStrength(String password) {
return patterns.stream().filter(password::matches).count();
}
static boolean checkStrength(String password) {
return passwordStrength(password) >= requiredPatterns;
}
Stream.of("", "foo", "BAR", "FooBar").forEach(pass -> {
System.out.println(pass);
System.out.println(passwordStrength(pass));
System.out.println(checkStrength(pass));
});
Your issue has been pointed out by another user, along with a solution. This is an alternative solution.
Have 4 Pattern objects, one for each requirement
Pattern uppercase = Pattern.compile("[A-Z]");
Pattern number = Pattern.compile("\\d+");
Pattern symbol = Pattern.compile("[+&$%!#]");
Pattern other = ...;
String#matches "compiles" the regex every time it is called, which can be time consuming. By using Pattern objects, you'll be using already-compiled regex patterns.
Add the requirements to a list
List<Pattern> requirements = Arrays.asList(uppercase, number, symbol, other);
Loop over the list of requirements. For each requirement, check if the password matches the requirement. If the element does, increase a counter which tracks how many requirements have already been met.
If the requirements equals 3 (or is greater than 3), return true. If the loop exits gracefully, that means 3 requirements were not met; return false if the loop exits gracefully.
public boolean isStrong(String password) {
int requirementsMet = 0;
for(Pattern req : requirements) {
if(req.matcher(password).matches())
requirementsMet++;
if(requirementsMet >= 3)
return true;
}
return false;
}
I assume the four requirements, of which at three must be met, are as follows. The string must contain:
a letter
a digit
a character in the string "!##$%^&*"
at least 8 characters
Is the use of a regular expression the best way to determine if a password meets three of the four requirements? That may be a valid question but it's not the one being asked or the one that I will attempt to answer. The OP may just be curious: can this problem be solved using a regular expression? Moreover, even if there are better ways to address the problem there is educational value in answers to the specific question that's been posed.
I am not familiar with Java, but I can suggest a regular expression that uses Ruby syntax. Readers unfamiliar with Ruby should be able to understand the expression, and its translation to Java should be straightforward. (If a reader can perform that translation, I would be grateful to see an edit to this answer that provides the Java equivalent at the end.)
r = /
((?=.*[a-z])) # match a lowercase letter in the string in
# a positive lookahead in cap grp 1, 0 times
((?=.*\d)) # match a digit in the string in a positive
# lookahead in cap grp 2, 0 times
((?=.*[!##$%^&*])) # match a special character in in the string
# in a positive lookahead in cap grp 3, 0 times
(.{8,}) # match at least 8 characters in cap grp 4, 0 times
\g<1>\g<2>\g<3> # match conditions 1, 2 and 3
| # or
\g<1>\g<2>\g<4> # match conditions 1, 2 and 4
| # or
\g<1>\g<3>\g<4> # match conditions 1, 3 and 4
| # or
\g<2>\g<3>\g<4> # match conditions 2, 3 and 4
/xi # case indiff & free-spacing regex def modes
\g{2}, for example, is replaced by the sub-expression contained in capture group 2 ((?=.*\d)). The first four lines each contain an expression in a capture group, with the capture group repeated zero times. This is just a device to define the subexpressions in the capture groups for retrieval later.
Let's test some strings.
"Passw0rd".match? r #=> true (a letter, digit and >= 8)
"ab2c#45d".match? r #=> true (all 4 conditions satisfied)
"ab2c#5d".match? r #=> true (a letter, digit and special char)
"ab2c345d".match? r #=> true (a letter, digit and >= 8)
"ab#c?def".match? r #=> true (a letter, special char and >= 8)
"21#6?512".match? r #=> true (a digit, special char and >= 8)
"ab26c4".match? r #=> false (only letter and digit)
"a$b#c".match? r #=> false (only letter and special char)
"abc ef h".match? r #=> false (only letter and >= 8)
"12 45 78".match? r #=> false (only digit and >=8)
"########".match? r #=> false (only special char and >= 8)
"".match r #=> false (no condition matched)
To use named capture groups, ((?=.*[a-z])) would be replaced with, say,
(?<letter>(?=.*[a-z]))
and \g<1>\g<2>\g<3> would be replaced by something like
\g<letter>\g<digit>\g<spec_char>
To answer your question, the sequence in which you have provided
1st: [a-zA-Z] characters
2nd: [0-9] Numbers
3rd: [!##$%^&*] Sp. Chars
The occurrence of literals in this sequence is must.
Abcd1234# will pass but Abcd1234#A will not pass, as A appears again after [!##$%^&*]
And a positive lookahead must include this sequence only. If you provied any special char before, it will not be validated, similarly in your case, characters after number is not expected.
use a positive lookahead for each combination, use groups for each
Try this instead(This is my work after several lookups):
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!##$%&*_])(?!.*[`~^=+/?<>():;-])(?=\S+$).{8,20}$
In this case: any of the provided chars or literals can appear anywhere.
(?=.*[0-9])
(?=.*[a-z])
(?=.*[A-Z])
(?=.*[!##$%&*_])
(?!.*[`~^=+/?<>():;-])
(?=\S+$)

Regular expression for phrase contain literals and numbers but is not all phrase as a number only with fixed range length

i want to have regular expression to check input character as a-z and 0-9 but i do not want to allow input as just numeric value at all ( must be have at least one alphabetic character)
for example :
413123123123131
not allowed but if have just only one alphabetic character in any place of phrase it's ok
i trying to define correct Regex for that and at final i raised to
[0-9]*[a-z].*
but in now i confused how to defined {x,y} length of phrase i want to have {9,31} but after last * i can not to have length block too i trying to define group but unlucky and not worked
tested at https://www.debuggex.com/
how can i to add it ??
What you seek is
String regex = "(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*";
Use it with String#matches() / Pattern#matches() method to require a full string match:
if (s.matches(regex)) {
return true;
}
Details
^ - implicit in matches() - matches the start of string
(?=.{9,31}$) - a positive lookahead that requires 9 to 31 any chars other than line break chars from the start to end of the string
\\p{Alnum}* - 0 or more alphanumeric chars
\\p{Alpha} - an ASCII letter
\\p{Alnum}* - 0 or more alphanumeric chars
Java demo:
String lines[] = {"413123123123131", "4131231231231a"};
Pattern p = Pattern.compile("(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*");
for(String line : lines)
{
Matcher m = p.matcher(line);
if(m.matches()) {
System.out.println(line + ": MATCH");
} else {
System.out.println(line + ": NO MATCH");
}
}
Output:
413123123123131: NO MATCH
4131231231231a: MATCH
This might be what you are looking for.
[0-9a-zA-Z]*[a-zA-Z][0-9a-zA-Z]*
To help explain it, think of the middle term as your one required character and the outer terms as any number of alpha numeric characters.
Edit: to restrict the length of the string as a whole you may have to check that manually after matching. ie.
if (str.length > 9 && str.length < 31)
Wiktor does provide a solution that involves more regex, please look at his for a better regex pattern
Try this Regex:
^(?:(?=[a-z])[a-z0-9]{9,31}|(?=\d.*[a-z])[a-z0-9]{9,31})$
OR a bit shorter form:
^(?:(?=[a-z])|(?=\d.*[a-z]))[a-z0-9]{9,31}$
Demo
Explanation(for the 1st regex):
^ - position before the start of the string
(?=[a-z])[a-z0-9]{9,31} means If the string starts with a letter, then match Letters and digits. minimum 9 and maximum 31
| - OR
(?=\d.*[a-z])[a-z0-9]{9,31} means If the string starts with a digit followed by a letter somewhere in the string, then match letters and digits. Minimum 9 and Maximum 31. This also ensures that If the string starts with a digit and if there is no letter anywhere in the string, there won't be any match
$ - position after the last literal of the string
OUTPUT:
413123123123131 NO MATCH(no alphabets)
kjkhsjkf989089054835werewrew65 MATCH
kdfgfd4374985794379857984379857weorjijuiower NO MATCH(length more than 31)
9087erkjfg9080980984590p465467 MATCH
4131231231231a MATCH
kjdfg34 NO MATCH(Length less than 9)
Here's the regex:
[a-zA-Z\d]*[a-zA-Z][a-zA-Z\d]*
The trick here is to have something that is not optional. The leading and trailing [a-zA-Z\d] has a * quantifier, so they are optional. But the [a-zA-Z] in the middle there is not optional. The string must have a character that matches [a-zA-Z] in order to be matched.
However, you need to check the length of the string with length afterwards and not with regex. I can't think of any way how you can do this in regex.
Actually, I think you can do this regexless pretty easily:
private static boolean matches(String input) {
for (int i = 0 ; i < input.length() ; i++) {
if (Character.isLetter(input.charAt(i))) {
return input.length() >= 9 && input.length() <= 31;
}
}
return false;
}

Replace leading zeros till decimal point with dash

If a string is a = 000102.45600. I need to convert it to a = ---102.45600.
Any help in java using either regex or String formatter?
Tried the following:
a = a.replaceFirst("^0+(?!$)","-");
but i am getting only a = -102.45600 not 3 dashes.
Rules: Any leading zeros before decimal in string should be replaced by that many dashes.
000023.45677 to ----23.45677
002345.56776 to --2345.56776
00000.45678 to -----.45678
Hopefully I am clear on what my need is?
String subjectString = "000102.45600";
String resultString = subjectString.replaceAll("\\G0", "-");
System.out.println(resultString); // prints ---102.45600
\G acts like \A (the start-of-string anchor) on the first iteration of replaceAll(), but on subsequent passes it anchors the match to the spot where the previous match ended. That prevents it from matching zeroes anywhere else in the string, like after the decimal point.
See: reference SO answer.
This should do it:
String number = //assign a value here
for (int i=number.length();i>0; i--) {
if (number.substring(0,i).matches("^0+$")) {
System.out.println(number.replaceAll("0","-"));
break;
}
}
This searches for the longest substring of number which starts at index 0 and consists entirely of zeroes - starting by checking the entire String, then shortening it until it finds the longest substring of leading zeroes. Once it finds this substring, it replaces each zero with a dash and breaks out of the loop.
Why not convert the start of the string to the "." to an integer, convert it back to a string then compare the lengths. 000102 length = 6. 102 length = 3. You would have your preceding zero count.

Password check using regex in Java

My application has a feature to check password. I need to get this scenario:
password length 10 ~ 32 .
It has to be a combination of either:
character and numbers
characters and special characters
numbers and special characters
Current code in application:
private boolean isSpecialMixedText(String password)
{
String number = "[0-9]";
String english = "[a-zA-Z]";
String special = "[!##\\$%^&*()~`\\-=_+\\[\\]{}|:\\\";',\\./<>?£¥\\\\]";
Pattern numberPattern = Pattern.compile(number);
Matcher numberMatcher = numberPattern.matcher(password);
Pattern englishPattern = Pattern.compile(english);
Matcher englishMatcher = englishPattern.matcher(password);
Pattern specialPattern = Pattern.compile(special);
Matcher specialMatcher = specialPattern.matcher(password);
return numberMatcher.find() && englishMatcher.find() || specialMatcher.find();
}
Please help me get the combination working
Actually, the regexes look fine. The problem is in this statement:
return numberMatcher.find() && englishMatcher.find() ||
specialMatcher.find();
It actually needs to be something like this:
boolean n = numberMatcher.find();
boolean e = englishMatcher.find();
boolean s = specialMatcher.find();
return (n && e) || (n && s) || (e && s);
And I agree with #adelphus' comment. Your rules for deciding what passwords are acceptable are very English-language-centric.
In my opinion your logic is wrong because you look for combination (so only these characters allowed) of: characters and numbers OR characters and special characters OR numbers and special characters. However with pair of matches like: [0-9] and [a-zA-Z] you are actually looking for a String with some digits and some letter, but it could be also 123ABC#$%#$%$#%#$ (because it has letters and digits).
What you need is something to check, if given string is composed ONLY of of allowed combination of characters. I think you can use one regex here (not too elegant, but effective) like:
^(?:((?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32})|((?=.*[-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[0-9].*)[0-9-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32})|((?=.*[-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[A-Za-z].*)[-A-Za-z!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32}))$
DEMO - it show valid and invalid matches.
This is quite long regex, but mainly because of you special character class. This regular expression is composed of three parts with similar structure:
positive lookagead for required characters + character class of
allowed characters
On an example:
(?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32}
means that string need to have:
(?=.*[A-Za-z].*) - at least one letter (positive lookahead for letter which could be surrounded by other characters),
(?=.*[0-9].*) - at least one number (positive lookahead for digit which could be surrounded by other characters)
[A-Za-z0-9]{10,32} - from 10 to 32 letters or digits,
in effect, the given password need to have 10 to 32 characters, but both letters and digits, proportion is not important.
Whats more, the ^ at beginning and $ in the end ensure that the whole examined string has such composition.
Also I would agree with others, it is not best idea to restrict allowed character in password like that, but it is your decision.

How to evaluate >9 number in a String expression Java

Life is very easy if the expression has values from 0 to 9 but
If expression = 23+52*5 is input by user then I take it in a String named expression.
Now what I want is that a new String or char Array in such a fashion that:
String s or char[] ch = ['23','+','52','*','5']
so that ch[0] or s.charAt(0) gives me 23 and not 2.
To do so I have tried the following and am stuck on what to do next:
for(int i=0;i<expression.length();i++)
{
int operand = 0;
while(i<expression.length() && sol.isOperand(expression.charAt(i))) {
// For a number with more than one digits, as we are scanning
// from left to right.
// Everytime , we get a digit towards right, we can
// multiply current total in operand by 10
// and add the new digit.
operand = (operand*10) + (expression.charAt(i) - '0');
i++;
}
// Finally, you will come out of while loop with i set to a non-numeric
// character or end of string decrement it because it will be
// incremented in increment section of loop once again.
// We do not want to skip the non-numeric character by
// incrementing it twice.
i--;
/**
* I have the desired integer value but how to put it on a string
* or char array to fulfill my needs as stated above.
**/
// help or ideas for code here to get desired output
}
In the while loop the method isOperand(char) is returning a boolean value true if char provided is >=0 or <=9.
You're going to want a String[] when you break the expression apart. Regex lookbehind/lookahead (Java Pattern Reference) allows you to split a String and keep the delimiters. In this case, your delimiters are the operands. You can use a split pattern like this:
public static void main(String[] args) throws Exception {
String expression = "23+52*5";
String[] pieces = expression.split("(?<=\\+|-|\\*|/)|(?=\\+|-|\\*|/)");
System.out.println(Arrays.toString(pieces));
}
Results:
[23, +, 52, *, 5]
One this to consider, is if your expression contains any spaces then you're going to want to remove them before splitting the expression apart. Otherwise, the spaces will be included in the results. To remove the spaces from the expression can be done with String.replaceAll() like this:
expression = expression.replaceAll("\\s+", "");
The "\\s+" is a regular expression pattern that means a whitespace character: [ \t\n\x0B\f\r]. This statement replaces all whitespace characters with an empty space essentially removing them.
String expr = "23+52*5";
String[] operands = expr.split("[^0-9]");
String[] operators = expr.split("[0-9]+");
This breaks it into:
try using a switch case:
//read first character
switch data
if number : what is it ( 0,1,2,3...?)
save the number
if its an operator
save operator
** 2 the switch has 4 cases for operators and 10 for digits **
// read the next character
again switch
if its a number after a number add both chars into a string
if its an operator "close" the number string and convert it into an int
If you will need some code I will gladly help.
Hope the answer is useful.
for i = 1 ; i = string.length
switch :
case 1,2,3,4,5,6,7,8,9,0 (if its a digit)
x(char) = char(i)
case +,-,*,/ (operator)
y(char) = char(i)
x[1] + x[2] +...x[n] = X(string) // build all the digits saves before the operator into 1 string
convert_to_int(X(string))
You can use regex:
\d+
Will grab any instance of one or more consecutive digits.

Categories

Resources