tags:

views:

147

answers:

7

I'm tired of writing

Pattern p = Pattern.compile(...
Matcher m = p.matcher(str);
if (m.find()) {
   ...

Over and over again in my code. I was going to write a helper class to make it neater, but I then I wondered: is there a library that tries to provide a simpler facade for Regular Expressions in Java?

I'm thinking something in the style of commons-lang and Guava.

CLARIFICATION: I am actually hoping for some general library that would make working with regular expression a more streamlined experience, kind of like how perl does it. The code above was just an example.

I was thinking of something I could use like this:

for (int question : RegEx.findAllInts("SO question #(\\d+)", str)) {
   // do something with int
}

Again, this is just an example of one of the many things I'd like to have. Probably not even a good example. APIs are hard.

UPDATE: I guess the answer is "No". Thanks for all the answers, have an upvote.

+1  A: 

Since Java 1.4, you can also use String.matches(String regex). Which precisely is a facade to the aforementionned code.

Riduidel
It does *not* do the same thing. It replaces the `find()` call with a `matches()` call. Of course that makes sense, if you look at the name, but it's a quite different operation.
Joachim Sauer
Not quite. `String.matches(regex)` is a short-cut for `Pattern.matches(regex, someString)`, not for `Matcher.find()`.
Bart Kiers
`find()` finds a substring in a String. `matches(...)` matches an entire input String: not the same thing! The API docs you linked to specifically says so: *"An invocation of this method of the form str.matches(regex) yields exactly the same result as the expression `Pattern.matches(regex, str)`"*
Bart Kiers
+2  A: 

Why not just write your own wrapper method? Sure, you should not reinvent the wheel but another library also means another dependency.

Helper Method
Same reason I like `StringUtils.isBlank` over my own implementation. When people implement reinvent the wheel, they tend to do it in subtly incompatible ways.
itsadok
Accepted since it seems this is my only option.
itsadok
+1  A: 

There is Jakarta Regexp (see the RE class). Have a look at this old thread for advantages of Jakarta's RegExp package over the Java built-in RegEx.

Pascal Thivent
Although Apache's RE are rather limited: no look arounds, for example.
Bart Kiers
@Bart Agreed, it's not very advanced but at the end, it really depends on the needs of the OP.
Pascal Thivent
There are no advantages to using Jakarta Regexp that I can see. It's still severely lacking in features, and the API is only slightly less clunky than that of the built-in package (which was the OP's only complaint anyway).
Alan Moore
+2  A: 

Pattern should only be compiled once; save it in a static final field. This at least saves you from repeating, at coding time an runtime, this step. That is to say, this step ought not always go hand-in-hand with creating a Matcher for performance reasons.

In your example, it seems RegEx plays the role of a Matcher object anyway. I hope it's not supposed to be a class with a static method since this would not work in a multithreaded environment -- the find and getInt calls are not connected then. So you need a Matcher of some sort anyway.

And so you're back to precisely the Java API, when design considerations are factored in. No I don't think there's a shorter way to do this correctly and efficiently.

Sean Owen
I changed my example to something that might be less offensive. Most of the time I don't care about efficiency. *Readability* is much more important. If you can use ThreadLocal and some more magic to make my simple code simple, I think it is worth it.
itsadok
+2  A: 

There is a java library which has extend feature over the built-in java regex library . Have a look at RegExPlus. I haven't tried it personally.But hope this helps.

TuxGeek
We're getting closer... That looks very interesting, even if not quite the direction I was looking for.
itsadok
Yeah, it doesn't do anything about streamlining the API, but very interesting in its own right.
Alan Moore
+1  A: 

For the specific example you give, you might be able to improvise something using Guava's splitter:

for (String number : Splitter.onPattern("[^\d]+").split(input)) {
    // Do something with the number
}

or more specifically, if you had input like

SO question #1234, SO Question #3456, SO Question #5678

you might do

for (String number : Splitter.onPattern("(, )? SO Question #").split(input)) {
    // Do something
}

It's a bit hacky, but in specific cases it may do what you're after.

Cowan
+2  A: 

Yeah, it's always bugged me, too, having to write so much boilerplate to perform such common tasks. I think it would help a lot if String had a pair of methods like

public String findFirst(String regex)

public String[] findAll(String regex)

These represent the two most commonly performed regex operations that aren't already supported by String methods. If we had those, plus a dynamic replacement facility like Rewriter, we could almost forget about Pattern and Matcher. We would only need them when we're writing something really complicated, like a findAllInts() method. :D

Alan Moore