patternjavaModerate
Recursive Regular Expressions
Viewed 0 times
recursiveregularexpressions
Problem
- I want to first search for a specific regular expression.
- If it is not found then I would like to search for another regular expression
- If that one is also not found then I would like to search for a third
- (And so on...)
Whenever a matching regular expression is found, I want to return a String array containing:
- The text before the match
- The match itself
- The text after the match
I've only come up with this horribly if-else nesting way of doing it. There's gotta be a better (more extensible and more clean) way but I can't come up with how...
Here is the code, it is currently only containing two regular expressions to search for and it's getting nasty already:
private static String[] findNumbers(String string) {
Matcher match = Pattern.compile("\\d+[\\:\\.\\,]\\d+").matcher(string);
if (match.find()) {
String found = string.substring(match.start(), match.end());
return new String[]{ string.substring(0, match.start()),
found, string.substring(match.end()) };
}
else {
match = Pattern.compile("\\d{3,}").matcher(string);
if (match.find()) {
String found = string.substring(match.start(), match.end());
return new String[]{ string.substring(0, match.start()),
found, string.substring(match.end()) };
}
else {
// Another if-else could be added here
return new String[]{ string, "", "" };
}
}
}
@Test
public void test() {
assertArrayEquals(new String[]{ "ABC ", "2000", " DEF" }, findNumbers("ABC 2000 DEF"));
assertArrayEquals(new String[]{ "42 ABC ", "2000", " DEF" }, findNumbers("42 ABC 2000 DEF"));
assertArrayEquals(new String[]{ "42 ABC ", "18:47", " DEF" }, findNumbers("42 ABC 18:47 DEF"));
}I want to put priority to one regular expression before trying the next, that's why I have written this code.
Solution
Nesting is not necessary, you can iterate instead...
But first:
Consider the following:
But first:
- naming the input String
stringcan be confusing. Of course it's a string, what is it used for though?
- there is no need to escape the values inside the
[...]construct. the pattern:"\\d+[:.,]\\d+"is just fine, and more readable.
- you should be pre-compiling and then reusing the patterns, instead of re-compiling them every time.
Consider the following:
private static final Pattern[] patternorder = {
Pattern.compile("\\d+[:.,]\\d+"),
Pattern.compile("\\d{3,}")
};
private static String[] findNumbers(String input) {
for (Pattern pat : patternorder) {
Matcher match = pat.matcher(input);
if (match.find()) {
return new String[] {
input.substring(0, match.start()),
input.substring(match.start(), match.end()),
input.substring(match.end()),
};
}
}
return new String[]{input, "", ""};
}Code Snippets
private static final Pattern[] patternorder = {
Pattern.compile("\\d+[:.,]\\d+"),
Pattern.compile("\\d{3,}")
};
private static String[] findNumbers(String input) {
for (Pattern pat : patternorder) {
Matcher match = pat.matcher(input);
if (match.find()) {
return new String[] {
input.substring(0, match.start()),
input.substring(match.start(), match.end()),
input.substring(match.end()),
};
}
}
return new String[]{input, "", ""};
}Context
StackExchange Code Review Q#39020, answer score: 10
Revisions (0)
No revisions yet.