Regular expression in java always return true - java

Can you please help me with regex for the following string in android:
1.0.2 Build S6B5
How it should be:
{number}.{number}.{number}{space}Build{space}{S or D orT}{anything up 3 to 4 chars}
With help of some king people from here I`ve tried the flowing code:
if (name.matches("\\d+\\.\\d+\\.\\d+\\s+Build\\s[SDT].{3,4}"));
but it always return True even for:
1.0.1 4C0
1.0.1 B 4BD
1.0.4.52A
etc.

Try the following code:
public static void main (String[] args) {
String name1 = "1.0.1 4C0";
String name2 = "1.0.1 B 4BD";
String name3 = "1.0.4.52A";
String name4 = "1.0.2 Build S6B5";
check(name1);
check(name2);
check(name3);
check(name4);
}
private static void check(String name) {
Pattern p = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\s+Build\\s+([SDT]\\w{3,4})");
Matcher m = p.matcher(name);
if (m.find()) {
System.out.println("num1: " + m.group(1));
System.out.println("num2: " + m.group(2));
System.out.println("num3: " + m.group(3));
System.out.println("build: " + m.group(4));
} else {
System.out.println("not found");
}
}
Use Matcher.find() method to match parts of the test string and then Matcher.group() method to access the parts captured by the round brackets.
Resulting output:
not found
not found
not found
num1: 1
num2: 0
num3: 2
build: S6B5

Try this one instead :
(\d{1}).(\d{1}).(\d{1})\s(Build)\s([SDT])([\w\d]{3,4})
or
(\d).(\d).(\d)*\s(Build)\s([SDT])([\w\d]{3,4}) if you can have multiple numbers.
In your, the problem is the end of the regex : ".{3,4}". It means that you accept ANY character 3 to 4 times.

Related

Camel-Case to Sentence-Case in Java

I have the following code to convert a camel-case phrase to sentence-case. It works fine for almost all cases, but it can't handle acronyms. How can this code be corrected to work with acronyms?
private static final Pattern UPPERCASE_LETTER = Pattern.compile("([A-Z]|[0-9]+)");
static String toSentenceCase(String camelCaseString) {
return camelCaseString.substring(0, 1).toUpperCase()
+ UPPERCASE_LETTER.matcher(camelCaseString.substring(1))
.replaceAll(matchResult -> " " + (matchResult.group(1).toLowerCase()));
}
JUnit5 test:
#ParameterizedTest(name = "#{index}: Convert {0} to sentence case")
#CsvSource(value = {"testOfAcronymUSA:Test of acronym USA"}, delimiter = ':')
void shouldSentenceCaseAcronym(String input, String expected) {
//TODO: currently fails
assertEquals(expected, toSentenceCase(input));
}
Output:
org.opentest4j.AssertionFailedError:
Expected :Test of acronym USA
Actual :Test of acronym u s a
I thought to add (?=[a-z]) to the end of the regex, but then it doesn't handle the spacing correctly.
I'm on Java 14.
Change the regex to (?<=[a-z])[A-Z]+|[A-Z](?=[a-z])|[0-9]+ where
(?<=[a-z])[A-Z]+ specifies positive lookbehind for [a-z]
[A-Z](?=[a-z]) specifies positive lookahead for [a-z]
Note that you do not need any capturing group.
Demo:
import java.util.regex.Pattern;
public class Main {
private static final Pattern UPPERCASE_LETTER = Pattern.compile("(?<=[a-z])[A-Z]+|[A-Z](?=[a-z])|[0-9]+");
static String toSentenceCase(String camelCaseString) {
return camelCaseString.substring(0, 1).toUpperCase() + UPPERCASE_LETTER.matcher(camelCaseString.substring(1))
.replaceAll(matchResult -> !matchResult.group().matches("[A-Z]{2,}")
? " " + matchResult.group().toLowerCase()
: " " + matchResult.group());
}
public static void main(String[] args) {
System.out.println(toSentenceCase("camelCaseString"));
System.out.println(toSentenceCase("USA"));
System.out.println(toSentenceCase("camelCaseStringUSA"));
}
}
Output:
Camel case string
USA
Camel case string USA
To fix your immediate issue you may use
private static final Pattern UPPERCASE_LETTER = Pattern.compile("([A-Z]{2,})|([A-Z]|[0-9]+)");
static String toSentenceCase(String camelCaseString) {
return camelCaseString.substring(0, 1).toUpperCase()
+ UPPERCASE_LETTER.matcher(camelCaseString.substring(1))
.replaceAll(m -> m.group(1) != null ? " " + m.group(1) : " " + m.group(2).toLowerCase() );
}
See the Java demo.
Details
([A-Z]{2,})|([A-Z]|[0-9]+) regex matches and captures into Group 1 two or more uppercase letters, or captures into Group 2 a single uppercase letter or 1+ digits
.replaceAll(m -> m.group(1) != null ? " " + m.group(1) : " " + m.group(2).toLowerCase() ) replaces with space + Group 1 if Group 1 matched, else with a space and Group 2 turned to lower case.

Java Best way to extract parts from a string

I have the following string;
[Username [rank] -> me] message
The characters of the rank, username, and message will vary each time. What is the best way I can break this into three separate variables (Username, rank and message)?
I have experimented with:
String[] parts = text.split("] ");
But it is throwing back errors. Thanks in advance!
Use Java's support for regular expressions (java.util.regex) and let a regex match the 3 parts.
For example this one: ^\[([\w]+) \[([\w]+)\] -> \w+\] (.*)$
Java code snippet, slightly adapted from Ian F. Darwin's "Java Cookbook" (O'Reilly):
import java.util.regex.*;
class Test
{
public static void main(String[] args)
{
String pat = "^\\[([\\w]+) \\[([\\w]+)\\] -> \\w+\\] (.*)$";
Pattern rx = Pattern.compile(pat);
String text = "[Username [rank] -> me] message";
Matcher m = rx.matcher(text);
if(m.find())
{
System.out.println("Match found:");
for(int i=0; i<=m.groupCount(); i++)
{
System.out.println(" Group " + i + ": " + m.group(i));
}
}
}
}
Output:
Match found:
Group 0: [Username [rank] -> me] message
Group 1: Username
Group 2: rank
Group 3: message
String input = "[whatever [Is] -> me] Input";
String user, rank, message;
user = input.substring(1, input.indexOf('[', 1));
rank = input.substring(input.indexOf('[', 1), input.indexOf(']'));
message = input.substring(input.lastIndexOf(']'));
this should work but if you really want it done right you should make a separate object that holds all this and can output it as a string. depends where this is coming from and where its going.
-axon

UNICODE Regex in java

In a combined regex it looks like working and it is failing when am using it in pattern. please help.
^(?=.*\\p{Nd})(?=.*\\p{L})(?!.*(.{2,})\\1).{5,12}$
this seems to be working but when I split it's failing.
^(?=.*\\p{Nd})(?=.*\\p{L})
Also I am looking for UNICODE validation to ignore any special character and just accept mixture of letters/Alpha & digits (atleast one alpha and one digit)
public void setValidations(){
validation1 = "^(?=.*\\p{Nd})(?=.*\\p{L})"; //this is failing
validation2 = "^.{5,12}$";
validation3 = "(\\S+?)\\1";
p1 = Pattern.compile(validation1);
p3 = Pattern.compile(validation3);
}
public boolean validateString(String str){
matcher1 = p1.matcher(str);
matcher3 = p3.matcher(str);
if(matcher1.find()){ //Expecting string passed "invalid" to fail (no numeric in it)
System.out.println(str + " String must have letters & number at least one");
return false;
}
if (!str.matches(validation2)){
System.out.println(str + " String must be between 5 and 12 chars in length");
return false;
}
if (matcher3.find()){
System.out.println(str + " got repeated: " + matcher3.group(1) + " String must not contain any immediate repeated sequence of characters");
return false;
}
return true;
}
public static void main(String[] args) {
StringValidation sv = new StringValidation();
String s2[] = {"1newAb", "A1DOALDO", "1234567AaAaAaAa", "123456ab3434", "$1214134abA", "invalid"};
boolean b3;
for(int i=0; i<s2.length; i++){
b3 = s2[i].matches("^(?=.*\\p{Nd})(?=.*\\p{L})(?!.*(.{2,})\\1).{5,12}$");
System.out.println(s2[i] + " "+ b3); // string "invalid" returning false (expected)
}
for (String str : s2) {
if(sv.validateString(str))
System.out.println(str + "String is Valid");
}
}
Also I want "$1214134abA" this string to fail since it has $
Pattern.compile("^(?=.*\\p{Nd})(?=.*\\p{L})").matcher("invalid").find() returns false as "invalid" does not contain a digit. Thus the if condition is evaluated to false and that block is skipped.
Use ^(?=[\\p{Nd}\\p{L}]*\\p{Nd})(?=[\\p{Nd}\\p{L}]*\\p{L}) to avoid characters other than letters and digits.
It will not accept $1214134abA as it contains $.
It seems that you forgot to use negation in
if(matcher1.find()){ //Expecting
...
return false;
}
It should return false if it will not find match. Try with
if(!matcher1.find()){ //Expecting...
Also since you want to check if your entire string is build on letters and digits instead of .{5,12} at the end try [\\p{L}\\p{Nd}]{5,12} .

Using regular expression to find a set number of + JAVA

I have a program where I want to filter Strings with a set number of "+"'s at the beginning.
For example:
+++Adam is working very well.
++Adam is working well.
+Adam is doing OK.
How do I only pick up each particular case (i.e. only one plus sign, only two plus signs, only three plus signs)? I usually get a return of anything beginning with a +.
I have the following regex patterns compiled, but I either get only one return (usually the two ++) or all of them:
public static String regexpluschar = "^\\Q+\\E{1}[\\w <]";
public static String regexpluspluschar = "^\\Q+\\E{2}[\\w <]";
public static String regexpluspluspluschar = "^\\Q+\\E{3}[\\w <]";
Pattern plusplusplus = Pattern.compile(regexpluspluspluschar);
Pattern plusplus = Pattern.compile(regexpluspluschar);
Pattern plus = Pattern.compile(regexpluschar);
I then try to find using a Matcher class - I've used .find() and .matches() but don't get the result I'm after (java+regex newbie alert here).
Matcher matcherplusplusplus = plusplusplus.matcher(check);
Matcher matcherplusplus = plusplus.matcher(check);
Matcher matcherplus = plus.matcher(check);
//OK we have 3+'s
if ((matcherplusplusplus.find())==true){
System.out.println("Filtering 3 +s.");
System.out.println("filter is " + filter + " in the 3 + filter.");
String toChange = getItem(i);
setItemFiltered(i, toChange);
}
//OK - we have 2 +'s
if ((matcherplusplus.find())==true){
System.out.println("Filtering 2 +s.");
System.out.println("filter is " + filter + " in the 2 + filter.");
String toChange = getItem(i);
setItemFiltered(i, toChange);
}
//OK - we have 1 +'s
if ((matcherplus.find())==true){
System.out.println("Filtering 1 +.");
System.out.println("filter is " + filter + " in the 1 + filter.");
String toChange = getItem(i);
setItemFiltered(i, toChange);
}
For the very curious, the above if's are embedded in a for loop that cycles around some JTextFields. Full code at: http://pastebin.ca/2199327
Why not simpler :
public static String regexpluschar = "^\\+[\\w <]";
public static String regexpluspluschar = "^\\+{2}[\\w <]";
public static String regexpluspluspluschar = "^\\+{3}[\\w <]";
or even
public static String regexpluschar = "^\\+[^\\+]";
public static String regexpluspluschar = "^\\+{2}[^\\+]";
public static String regexpluspluspluschar = "^\\+{3}[^\\+]";
Edit : It's working on my test program, but I had to removed your specific code :
String toChange = getItem(i);
setItemFiltered(i, toChange);
proof : my output is :
Filtering 3 +s.
+++Adam is working very well. is in the 3 + filter.
Filtering 2 +s.
++Adam is working well. is in the 2 + filter.
Filtering 1 +.
+Adam is doing OK. is in the 1 + filter.
Your filter is working, but you specific code may not... (maybe have a look at setItemFiltered?)
I was thinking something like this would be easier:
public static void main(String[] args) {
Pattern pattern = Pattern.compile("^(\\+{1,3}).*");
Matcher matcher = pattern.matcher(<your text>);
if (matcher.matches()) {
String pluses = matcher.group(1);
switch (pluses.length()) {
}
}
}
And if you want to be sure that ++++This is insane does not match then change the pattern to
Pattern pattern = Pattern.compile("^(\\+{1,3})[^+].*");

java regex separate numbers from strings

I have got strings like:
BLAH00001
DIK-11
DIK-2
MAN5
so all the strings are a kind of (sequence any characters)+(sequence of numbers)
and i want something like this:
1
11
2
5
in order to get those integer values, i wanted to separate the char sequence and the number sequence an do something like Integer.parseInt(number_sequence)
Is there something that does this job?
greetings
Try this:
public class Main {
public static void main(String[]args) {
String source = "BLAH00001\n" +
"\n" +
"DIK-11\n" +
"\n" +
"DIK-2\n" +
"\n" +
"MAN5";
Matcher m = Pattern.compile("\\d+").matcher(source);
while(m.find()) {
int i = Integer.parseInt(m.group());
System.out.println(i);
}
}
}
which produces:
1
11
2
5
String[] a ={"BLAH00001","DIK-11","DIK-2","MAN5"};
for(String g:a)
System.out.println(Integer.valueOf(g.split("^[A-Z]+\\-?")[1]));
/*******************************
Regex Explanation :
^ --> StartWith
[A-Z]+ --> 1 or more UpperCase
\\-? --> 0 or 1 hyphen
*********************************/
Pattern p = Pattern.compile("^[^0-9]*([0-9]+)$");
Matcher m = p.matcher("ASDFSA123");
if (m.matches()) {
resultInt = Integer.parseInt(m.group(1)));
}
Maybe you want to have a look to Java Pattern and Matcher:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html
http://leepoint.net/notes-java/data/strings/40regular_expressions/26pattern-matcher.html
http://answers.yahoo.com/question/index?qid=20071106173149AA4TUON

Categories

Resources