Java: substring.matches numbers - java

I'm trying to check if a my substring within my teleInput string contain numbers but I can't seem to get it return true. The results always ends up as false, what am I doing wrong.
String teleInput = "(555)555-5555";
boolean returntT = teleInput.substring(1,3).matches(".*[0-9].*");
I'm an extreme beginner so I don't know if I'm missing something obvious, like mixing methods or maybe something is wrong with the rest of my code, either way, I would really appreciate the help!

Your problem is your substring - you are only returning two characters: the second parameter is the index up to, but not including, the last character. To get 3 characters, you need:
teleInput.substring(1,4)
So try this (notice that matches only needs to check that it's "all digits", because the length is already know to be 3):
teleInput.substring(1,4).matches("\\d*");
Or just forget substring and use matches alone:
teleInput.matches(".\\d{3}.*");
Which is the regex for "any character then 3 digits then anything".
But you can validate the entire input in one line:
teleInput.matches("(.\\d{3}){3}\\d");
You might have to read up on regex to understand this pattern, but it works!
Note: matches() must match the entire string to be true.

If you want to check if the 2nd character in your string is number, you can do it like this:
String teleInput = "(555)555-5555";
boolean returntT = teleInput.substring(1,2).matches("[0-9]");

Instead of this line:
boolean returntT = teleInput.substring(1,3).matches(".*[0-9].*");
You should be doing:
boolean returntT = teleInput.substring(1,3).matches("[0-9]+");
OR this:
boolean returntT = teleInput.substring(1,3).matches("\\d{2}");
Regex [0-9]+ will make sure that the given input has only 1 or more digits in it. For good tutorial on regex read: http://www.regular-expressions.info/

Related

How to check if a word ends and starts with a common symbol and replace it as many times it appears with 1

I am facing a little challenge, here's what I've been trying to do.
Assuming I have these 2 variables
String word1 ="hello! hello!! %can you hear me%? Yes I can.";
And then this one
String word2 ="*Java is awesome* Do you % agree % with us?";
I want to be able to check if a variable contains a word that begins and ends with a particular symbol(s) like % and * that I am using and replace with; with '1' (one). Here's what I tried.
StringTokenizer st = new StringTokenizer(word1);
while(st.hasMoreTokens()){
String block = st.nextToken();
if( (block.startsWith("%") && block.endsWith("%") ||(block.startsWith("*") && block.endsWith("*")){
word1.replace (block,"1");
}
}
//output
'hello!hello!!%canyouhearme%?YesIcan."
//expected
"hello! hello!! 1? Yes I can.";
It just ended up trimming it. I guess this is because of the delimiter used is Space and since the last % ends with %? It read it as a single block.
When I tried the same for word2
I got "1Doyou%agree%withus?"
//expected
"1 Do you 1 with us?"
And assuming I have another word like
String word3 ="%*hello*% friends";
I want to be able to produce
//output
"1friends"
//expected
"11 friends"
Since it has 4-symbols
Any help would be truly appreciated, just sharpening my java skills. Thanks.
You can use a Regular Expression (RegEx) within the String.matches() method for determining if a string contains the specific criteria, for example:
if (word1.matches(".*\\*.*\\*.*|.*\\%.*\\%.*")) {
// Replace desired test with the value of 1 here...
}
If you want the full explanation of this regular expression then go to rexex101.com and enter the following expression: .*\*.*\*.*|.*\%.*\%.*.
The above if statement condition utilizes the String.matches() method to validate whether or not the string contains text (or no text) between either asterisks (*) or between percent (%) characters. If it does we simply use the String.replaceAll() method to replace those string sections (between and including *...* and %...%) with the value of 1, something like this:
String word1 = "hello! hello!! %can you hear me%? Yes I can.";
if (word1.matches(".*\\*.*\\*.*|.*\\%.*\\%.*")) {
String newWord1 = word1.replaceAll("\\*.*\\*|%.*%", "1");
System.out.println(newWord1);
}
The Console window will display:
hello! hello!! 1? Yes I can.
If you were to play this string: "*Java is awesome* Do you % agree % with us?" into with the above code your console window will display:
1 Do you 1 with us?
Keep in mind that this will provide the same output to console if your supplied string was "** Do you %% with us?". If you don't really want this then you will need to modify the RegEx within the matches() method a wee bit to something like this:
".*\\*.+\\*.*|.*\\%.+\\%.*"
and you will need to modify the the RegEx within the replaceAll() method to this:
"\\*.+\\*|%.+%"
With this change there now must be text between both the asterisks and or the Percent characters before validation is successful and a change is made.
The question isn't clear (not sure about how %*hello*% somehow translates to 11, and didn't understand what you mean by Since it has 4-symbols), but wouldn't regular expressions work?
Can't you simply do:
String replaced = word1.replaceAll("\\*[^\\*]+\\*", "1")
.replaceAll("\\%[^\\%]+\\%", "1");
I would say your presumption that special characters will be replaced twice is wrong. Replace function only works with case when you are trying to replace occurance of String, which doesn't seem to work with special characters. Only replaceAll, seems to work in that case. In your code you are trying to replace special characters along with other strings inside that, so only replaceAll function will do so.
In other words, when replaceAll function is executed it checks occurance of special characters , and replaces it once. You wouldn't require effort of using StringTokenizer, which is part of Scanner library, it is only required if you are taking user's input. So, no matter what you do you would only see 1 friends instead of 11 friends , also , you wouldn't need if statement. Credit goes to jbx above for regex. Now, you could shorten your code like this, still bearing in mind that 1 is printed replacing whatever is inside special character is replaced by single number 1.
You will need if-statement to search , replaceAll, or replace function already searches in String you specify to search on, so that if-statement is redundant, it's just making code end up being verbose.
package object_list_stackoverflow;
import java.util.StringTokenizer;
public class Object_list_stackoverflow {
public static void main(String[] args) {
String word1 = "hello! hello!! %can you hear me%? Yes I can.";
String word2 ="*Java is awesome* Do you % agree % with us?";
String word3 ="%*hello*% friends";
String regex = "\\*[^\\*]+\\*";
String regex1= "\\%[^\\%]+\\%";
System.out.println(word3.replaceAll(regex, "1").replaceAll(regex1, "1"));
}
}
Also read similar question by going to : Find Text between special characters and replace string
You can also get rid of alphanumeric characters by looking at dhuma1981's answer: How to replace special characters in a string?
Syntax to replace alphanumerics in String :
replaceAll("[^a-zA-Z0-9]", "");

java - Fix an invalid Duration

We get xml with invalid duration, like PT10HMS (note lack of numbers before M and S). I have handled this by reading the file and fixing by iterating the duration string character by character and inserting 0 between 2 letters that are side by side (except between P and T). I was wondering if there was a more elegant solution maybe using a regex with sed or anything else?
thanks for any suggestions
An idea for a Java solution here (sure sed can be used too).
String incorrectDuration = "PT10HMS";
String dur = incorrectDuration.replaceAll("(?<!\\d+)[HMS]", "0$0");
This produces
PT10H0M0S
Personally I would prefer deleting the letters that do not have a number in front of them:
String dur = incorrectDuration.replaceAll("(?<!\\d+)[HMS]", "");
Now I get
PT10H
In both cases Duration.parse(dur) works and gives the expected result.
(?<!\\d+) is a negative lookbehind: with this the regex only matches if the H, M or S is not preceded by a string of digits.
Edit: I am probably overdoing it in the following. I was just curious how I could produce my preferred string also in the case where you have got for example PTHMS as you mentioned in the comment. For production code you will probably want to stick with the simpler solution above.
String durationString = "PTHMS";
// if no digits, insert 0 before last letter
if (! durationString.matches(".*\\d.*")) {
durationString = durationString.replaceFirst("(?=[HMS]$)", "0");
}
// then delete letters that do not have a digit before them
durationString = durationString.replaceAll("(?<!\\d)[HMS]", "");
This produces
PT0S
(?=[HMS]$) is a lookahead. It matches the empty string but only if this empty string is followed by either H, M or S and then the end of the string. So replacing this empty string with 0 gives us PTHM0S. Confident that there is now at least one digit in the string, we can proceed to delete letters that don’t have a digit before them.
It still wouldn’t work if you had just PT. As I understand, this doesn’t happen. If it did, you would prefer for example durationString = PT0S; inside the if statement instead.

My code with matches() is not working. Why is it not working?

I am trying to create a small program that reads a password and determines if it is a password you can use. I was using matches() to see if it has at least one letter (uppercase or lowercase) and one digit as well as be 6 characters long. I try to use matches like this:
if ( passwordLength >= 6
&& password.matches("[A-Za-z]")
&& password.matches("\\d")
) {
System.out.println("Valid Password.");
}
else {
System.out.println("Invalid Password.");
}
Im not sure what i am doing wrong. Please help.
matches function should try to match the whole string using the regex we gave. So instead of using two or more matches functions for condition checking, you may use a single one with a complex regex. And also it seems like your password would contain not only digits or letters but also some other characters too.
string.matches("^(?=.*[a-zA-Z])(?=.*\\d).{6,}$");
(?=.*[a-zA-Z]) Positive lookahead which asserts that the string going to be matched must contain atleast one letter.
(?=.*\\d) asserts it must contain atleast one digit.
.{6,} ensures that the length must be atleast 6 and atmost any..
For the length to be exactly 6 then change .{6,} in the above to .{6}
DEMO
It looks like you're misinterpreting the matches function, which matches over the entire input, while you're expecting it to return true if a substring matches. As others suggested, you'll need to use a single regex and matches() call since you're asking if the string is a single character AND a number (which would never be true).
Another important point, though it may not be important to you, is that a password should never be stored as a String object since they're immutable and can persist long enough for something else to come along and read it. More on that here.
There are a couple of things wrong with your code:
Your regex is wrong. You are only matching on 1 character, so you should change the [a-z] to [a-z]+.
You are matching on 'it should be bigger than 6, should be a character, AND it should be a number. That's different from your requirement.

regex can't get special constructs (?=x) to work

I'm trying to get a valid regex to use in java (java.util.regex) that validates the following format:
a number that has max 15 digits, of which 3 MAX digits may be decimal which are preceeded by a separator (,)
So, valid would be:
123456789012345 (15 digits, ok)
12345678901234,1
[EDIT], these should also be valid:
1234567890123,45
123456789012,345
So far i've come up with the following regex pattern:
Pattern = [0-9]{1,15}(\,[0-9]{1,3})?
This checks for a a range of 1 to 15 digits, following by an optional separator followed by another 3 digits. However, this doesnt check the total length of the input. With this regex, a value of 123456789012345,123 would be valid.
So, i thought i'd add an extra expression that checks the total length, and use the "(?=" construct to simulate the logical AND behaviour.
So i started with adding that to my existing regex expression as follows:
Pattern = (?= [0-9]{1,15}(\,[0-9]{1,3})?)
This however results in basically everything i throw at it failing, and i cant get it to work further. I don't see what i'm doing wrong here? After this works, i'd add another expression to check total length, something like (?=.{16}) i think.
[EDIT]
Realised you wanted to accept total length of 16 if there is a ,, and also that you don't really need to use lookaround here, since you only have two cases. This works just fine:
public static boolean isValid(String input) {
return input.matches("^(\\d{0,15}|\\d{1,12},\\d{1,3})$");
}
This returns valid if one of these is true
input consists of 0-15 numbers or
input consists of 1-12 numbers, followed by a ,, followed by 1-3 numbers
[EDIT2]
Ok, new try:
public static boolean isValid(String input) {
return input.matches("^(\\d{0,15}|(?=.{3,16})\\d+,\\d{1,3})$");
}
This returns valid if one of these is true
input consists of 0-15 numbers or
input consists of 3-16 characters, consisting of at least one digit, followed by a ,, followed by 1-3 numbers
What about this one? play it on RegExr
\d{12,15},?\d{3}
this worked for me.
boolean a = Pattern.matches("\\d{15}|\\d{12},\\d{3}", "123456789012345");
System.out.println(a);//true
boolean b = Pattern.matches("\\d{15}|\\d{12},\\d{3}", "123456789012,345");
System.out.println(b);//true
boolean c = Pattern.matches("\\d{15}|\\d{12},\\d{3}", "1234567890123,456");
System.out.println(c);//false
so your regEx is:
\d{15}|\d{12},\d{3}
Try this regex:
^\d{1,12}(?:\d{0,3}|\d{0,2},\d|\d{0,1},\d\d|,\d\d\d)$

Matcher returns matches on a regex pattern, but split() fails to find a match on the same regex?

I can't see a reason why the Matcher would return a match on the pattern, but split will return a zero length array on the same regex pattern. It should return something -- in this example I'm looking for a return of 2 separate strings containing "param/value".
public class MyClass {
protected Pattern regEx = "(([a-z])+/{1}([a-z0-9])+/?)*";
public void someMethod() {
String qs = "param/value/param/value";
Matcher matcherParamsRegEx = this.regEx.matcher(qs);
if (matcherParamsRegEx.matches()) { // This finds a match.
String[] parameterValues = qs.split(this.regEx.pattern()); // No matches... zero length array.
}
}
}
The pattern can match the entire string. split() doesn't return the match, only what's in between. Since the pattern matches the whole string that only leaves an empty string to return. I think you might be under a misconception as to what split() does.
For example:
String qs = "param/value/param/value";
String pieces = qs.split("/");
will return an array of 4 elements: param, value, param, value.
Notice that what you search on ("/") isn't returned.
Your regex is somewhat over-complicated. For one thing you're using {1}, which is unnecessary. Second, when you do ([a-z])+ you will capture exactly one latter (the last one encountered. Compare that to ([a-z]+), which will capture the entire match. Also, you don't even need to capture for this. The pattern can be simplified to:
protected Pattern regEx = Pattern.compile("[a-z]+/([a-z0-9]+/?)*");
Technically this:
protected Pattern regEx = "(([a-z])+/{1}([a-z0-9])+/?)*";
is a compiler error, so what you actually ran versus what you posted could be anything.
The problem here is that split splits around matches of your regex. You have two consecutive matches with nothing else in between, so there is nothing left for split to return.
I can't see any way for you to get what you want from that string using split, but if you can use a different delimiter to separate pairs than you do to separate name and value, that will help a lot.
Otherwise, you might split on slashes and take alternating results as names and values, but this is error-prone.
The regex is matching--if it weren't, you would get a one-element array, that element being the whole original string. You just have the wrong idea about how split() works. On the first match attempt it finds "param/value/" and stores everything preceding that match as the first token: an empty string. The second attempt finds "param/value" and stores whatever lay between it and the first match as the next token: another empty string. The third match attempt fails, so whatever was between the second match and the end of the string becomes the final token: yet another empty string.
Having stored all the tokens, split() iterates through them in reverse, checking for trailing empty tokens. The third token is indeed empty, so it deletes that one. The second one is also empty, so it deletes that one. You see where this is going? You can force split() to preserve trailing empty matches by passing a negative integer as the second argument, but that obviously doesn't do you any good. You need to rethink your problem (whatever it is) in terms of how the regex package actually works.

Categories

Resources