I have a string of format :
"A hr B min to C hr D min"
where A, B, C, D will be integers. I want to extract A, B, C, D from this string. A, B, C, D can be single or multi digit integers and I am not really concerned with validation right now (such as C, D would be between 0 and 59 ideally) as that can be taken care of later.
What is the best way to achieve this in Java?
Assuming this text could appear inside a larger text, and that your target phrase might be repeated more than once, we can try matching on the following pattern:
\b(\d+) hr (\d+) min to (\d+) hr (\d+) min\b
Here is a sample Java code:
String input = "blah blah 1 hr 5 min to 2 hr 10 min blah blah";
String regex = "\\b(\\d+) hr (\\d+) min to (\\d+) hr (\\d+) min\\b";
Pattern r = Pattern.compile(regex);
Matcher m = r.matcher(input);
while (m.find()) {
System.out.println("Found values: (" + m.group(1) + ", " + m.group(2) + ", " +
m.group(3) + ", " + m.group(4) + ")");
}
This prints:
Found values: (1, 5, 2, 10)
public class splitString {
public static void main(String[] args) {
String hours = "5 hr 6 min to 17 hr 09 min";
String[] splithours = hours.split(" ");
for(String splitted: splithours) {
if(splitted.matches("[0-9]{2}") || splitted.matches("[0-9]") ) {
System.out.println(splitted);
}
}
}
}
Related
My String:
BByTTheWay .I want to split the string as B By T The Way BByTheWay .That means I want to split string if I get any capital letters and last put the main string as it is. As far I tried in java:
public String breakWord(String fileAsString) throws FileNotFoundException, IOException {
String allWord = "";
String allmethod = "";
String[] splitString = fileAsString.split(" ");
for (int i = 0; i < splitString.length; i++) {
String k = splitString[i].replaceAll("([A-Z])(?![A-Z])", " $1").trim();
allWord = k.concat(" " + splitString[i]);
allWord = Arrays.stream(allWord.split("\\s+")).distinct().collect(Collectors.joining(" "));
allmethod = allmethod + " " + allWord;
// System.out.print(allmethod);
}
return allmethod;
}
It givs me the output: B ByT The Way BByTTheWay . I think stackoverflow community help me to solve this.
You may use this code:
Code 1
String s = "BByTTheWay";
Pattern p = Pattern.compile("\\p{Lu}\\p{Ll}*");
String out = p.matcher(s)
.results()
.map(MatchResult::group)
.collect(Collectors.joining(" "))
+ " " + s;
//=> "B By T The Way BByTTheWay"
RegEx \\p{Lu}\\p{Ll}* matches any unicode upper case letter followed by 0 or more lowercase letters.
CODE DEMO
Or use String.split using same regex and join it back later:
Code 2
String out = Arrays.stream(s.split("(?=\\p{Lu})"))
.collect(Collectors.joining(" ")) + " " + s;
//=> "B By T The Way BByTTheWay"
Use
String s = "BByTTheWay";
Pattern p = Pattern.compile("[A-Z][a-z]*");
Matcher m = p.matcher(s);
String r = "";
while (m.find()) {
r = r + m.group(0) + " ";
}
System.out.println(r + s);
See Java proof.
Results: B By T The Way BByTTheWay
EXPLANATION
--------------------------------------------------------------------------------
[A-Z] any character of: 'A' to 'Z'
--------------------------------------------------------------------------------
[a-z]* any character of: 'a' to 'z' (0 or more
times (matching the most amount possible))
As per requirements, you can write in this way checking if a character is an alphabet or not:
char[] chars = fileAsString.toCharArray();
StringBuilder fragment = new StringBuilder();
for (char ch : chars) {
if (Character.isLetter(ch) && Character.isUpperCase(ch)) { // it works as internationalized check
fragment.append(" ");
}
fragment.append(ch);
}
String.join(" ", fragment).concat(" " + fileAsString).trim(); // B By T The Way BByTTheWay
I have a string "Spec Files: 15 passed, 5 failed, 20 total (100% completed) in 00:08:53".
I need to use regex and print the following:
Passed: 15
Failed: 5
Total: 20
And also need to compute and print the pass percentage. Pls help.
I'm using below code:
String line = "Spec Files: 15 passed, 5 failed, 20 total (100% completed) in 00:08:53";
Pattern p = Pattern.compile("(\\d+)\\s+");
Matcher m = p.matcher(line);
while(m.find()) {
System.out.println(m.group());
}
You need a regex that captures the 2 elements you need : text and value, then print them in the good order :
String line = "Spec Files: 15 passed, 5 failed, 20 total (100% completed) in 00:08:53";
Pattern p = Pattern.compile("(\\d+)\\s+(\\w+)");
Matcher m = p.matcher(line);
while (m.find()) {
System.out.println(m.group(2) + ": " + m.group(1));
}
/*
passed: 15
failed: 5
total: 20
capitalize is not a built-in function so you can take a look at How to capitalize the first character of each word in a string
Pass %:
Map<String, Integer> map = new HashMap<>();
while (m.find()) {
System.out.println(m.group(2) + ": " + m.group(1));
map.put(m.group(2), Integer.parseInt(m.group(1)));
}
double passPercentage = map.get("passed") / (double) map.get("total");
System.out.println(passPercentage);
OR
int passed = 0, total = 0;
while (m.find()) {
System.out.println(m.group(2) + ": " + m.group(1));
if (m.group(2).equals("passed")) {
passed += Integer.parseInt(m.group(1));
} else if (m.group(2).equals("total")) {
total += Integer.parseInt(m.group(1));
}
}
double passPercentage = passed / (double) total;
System.out.println(passPercentage);
I've been working on matching a variable from a client. It reads as such:
0s
12s
1m15s
15m0s
1h0m5s
1h15m17s
I would like to capture all three groupings of digits within a single find.
(\d+)(?=h(\d+)m(\d+))*?(?=m(\d+))*?
The regex I have been working on above however will only grab the successive groups in each new find.
example:
input is 12s group 1 is 12 ... works.
input is 1m12s group 1 is 1 however to get the 12, I have to use find again to get to the next group of 12.
Just as note as it didn't occur to me right away, make sure to do a check if a group is null for capturing groups that are optional.
Try this way:
((\d+)h)?((\d+)m)?((\d+)s)
Then you capture group 2 for hour, group 4 for minutes and group 6 for seconds
See it working here: https://regex101.com/r/bZ4zW4/2
In a graphical way:
Debuggex Demo
EDIT
To get the results in JAVA (since your last edit) do as follow:
Pattern p = Pattern.compile("((\\d+)h)?((\\d+)m)?((\\d+)s)");
Matcher m = p.matcher("1h15m17s");
if (m.find()){
Integer hour = Integer.valueOf(m.group(2));
Integer minute = Integer.valueOf(m.group(4));
Integer second = Integer.valueOf(m.group(6));
System.out.println(hour + " - " + minute + " - " + second);
}
m = p.matcher("1h0m5s");
if (m.find()){
Integer hour = Integer.valueOf(m.group(2));
Integer minute = Integer.valueOf(m.group(4));
Integer second = Integer.valueOf(m.group(6));
System.out.println(hour + " - " + minute + " - " + second);
}
m = p.matcher("15m0s");
if (m.find()){
Integer minute = Integer.valueOf(m.group(4));
Integer second = Integer.valueOf(m.group(6));
System.out.println(minute + " - " + second);
}
m = p.matcher("12s");
if (m.find()){
Integer second = Integer.valueOf(m.group(6));
System.out.println(second);
}
m = p.matcher("0s");
if (m.find()){
Integer second = Integer.valueOf(m.group(6));
System.out.println(second);
}
The output will be respectively:
1 - 15 - 17
1 - 0 - 5
15 - 0
12
0
Note that in each case I'm getting a specific value. If you try to get a minute from a matcher that is nonexistent you will get a java.lang.NumberFormatException because it will return null. So you must check it first. This below block will end up in the mentioned exception:
m = p.matcher("0s");
if (m.find()){
Integer minute = Integer.valueOf(m.group(4)); //exception here
Integer second = Integer.valueOf(m.group(6));
System.out.println(second);
}
If I am given a integer value like 100, then I have to update all the occurrences of the text "Writing No 1" to "Writing No 101"
Actual text:
Collection reference 4 -> My Main Text 4 -> It's writing 3 Writing No 1
Writing No 2 Writing NO 3
I have given three previous references.
As I am given the 100, so I output would like this.
Collection reference 4 -> My Main Text 104 -> It's writing 3 Writing No 101
Writing No 102 Writing NO 103
I have given three previous references.
How to update Writing No 1 to Writing NO 101 and other in the same way using Java?
As per my understanding from your question, you got to replace the string based on the integer values.
Better you write a function for the same like this-
String text = new String("Writing No 1");
public void demo(int num) {
text .replace(text.slice(-1), num);
}
Where you can pass any integer value and can even use loop for the multiple string values.
Hope i was helpful.
Not 100% this is what you need, but I'll give it a try:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StackOverflow {
public static void main(String[] args) {
int inc = 100;
String text = "Collection reference 4 -> My Main Text 4 -> It's writing 3 Writing No 1 \nWriting No 2 Writing NO 3 \nI have given three previous references.";
String patten = "(\\D+) (\\d) (\\D+) (\\d) (\\D+) (\\d) (\\D+) (\\d) (\\D+) (\\d) (\\D+) (\\d) (\\D+)";
Pattern pattern = Pattern.compile(patten, Pattern.DOTALL);
Matcher matcher = pattern.matcher(text);
matcher.find();
System.out.println(matcher.group(1) + " " + matcher.group(2) + " " + matcher.group(3) + " "
+ inc(matcher.group(4), inc) + " " + matcher.group(5) + " " + matcher.group(6) + " " + matcher.group(7)
+ " " + inc(matcher.group(8), inc) + " " + matcher.group(9) + " " + inc(matcher.group(10), inc) + " "
+ matcher.group(11) + " " + inc(matcher.group(12), inc) + matcher.group(13));
}
private static int inc(String base, int inc) {
return Integer.valueOf(base) + inc;
}
}
I am trying to split an inputted number such as (123) 456-7890.
String [] split = s.split(delimiters);
I have been searching the web for ways of delimiting the area code inside the set of the parentheses but I haven't found anything that works for my case. I do not know if the array is messing up with it printing either. The array is not required but I did not know what else to do since it is required to use the split method.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HelloWorld{
public static void main(String[] args){
String phoneNumber = "(123)-456-7890";
String pattern = "\\((\\d+)\\)-(\\d+)-(\\d+)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(phoneNumber);
if (m.find())
System.out.println(m.group(1) + " " + m.group(2) + " " + m.group(3));
}
}
You can try it here.
If I understand your question, you could use a Pattern like (XXX) XXX-XXXX where X is a digit. You can also use {n} to require n occurences. You group with (). Something like,
String str = "(123) 456-7890";
Pattern p = Pattern.compile("\\((\\d{3})\\) (\\d{3})-(\\d{4})");
Matcher m = p.matcher(str);
if (m.matches()) {
String areaCode = m.group(1);
String first3digits = m.group(2);
String last4digits = m.group(3);
System.out.printf("(%s) %s-%s%n", areaCode, first3digits,
last4digits);
}
Gives your requested output of
(123) 456-7890
or, if you must use split you might first remove the ( and ) with a call to replaceAll and something like
String str = "(123) 456-7890";
String[] arr = str.replaceAll("[()]", "").split("[ -]");
System.out.printf("(%s) %s-%s%n", arr[0], arr[1], arr[2]);
which also gives your requested output of
(123) 456-7890
this works:
String s= "(123) 456-7890";
String[] parts = s.split("[()\\- ]");
System.out.println("(" + parts[1] + ") " + parts[3] + "-" + parts[4]);
If you must use the split method:
String s= "(123) 456-7890"
String[] split = s.split("[()-]");
System.out.println("(" + split[1] + ")" + split[2] + "-" + split[3]);