Using replaceAll with Groovy regular expressions

String.replaceAll can take regular expression pattern arguments. Tried it with a Groovy script and had a compile error.

Ooops! Figured it out. In a slashy string, those using ‘/’ as terminators, the last character cannot be a ‘\’ since that will escape the terminator character, ‘/’. Thus,

def pattern = ~/\\/

Will not compile. But, this:

def pattern = ~/\${''}/

will. It is documented, I just kept missing it.

That is why it is used here:

println /c:\a\b\c\d/.replaceAll((/\\${''}/),"/")

Alternatively, if your using Groovy 1.8* you can use the new $//$ slashy string:

println ( /c:\a\b\c\d/.replaceAll(($/\\/$),"/")  )

or

println ( (/c:\a\b\c\d/ =~ $/\\/$).replaceAll("/") )

I was reading this blog post on the need to sometimes not use regular expression in Java: “Tip #5 Avoid RegEx When Unnecessary.”

To take the string “c:\a\b\c\d” and convert it to “c:/a/b/c/d”, just do s.replace(‘\\’, ‘/’);. Don’t use regexp. And, I thought, it would be easy to still use regular expressions if Groovy were used, doesn’t the slashy string remove the backslash headache?

Example that gets compile error:

println "new is: " +  /c:\a\b\c\d/.replaceAll((/\\/),"/")
C:\temp>groovy test.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\temp\test.groovy: 2: expecting anything but ''\n''; got it anyway @ line 2, column 58.
   \b\c\d/.replaceAll((/\\/),"/")
                                 ^
1 error

I also tried using a compiled pattern, pat = ~/\\/, but that did not work either, neither did a few other things. For example, this doesn’t work either:

println  (/c:\a\b\c\d/ =~ /\\/).replaceAll("/")

The first set of parenthesis should have returned a Matcher object, and then the replaceAll called on it. Instead, we get:
C:\temp\test.groovy: 1: unexpected char: 0xFFFF @ line 1, column 47.
\c\d/ =~ /\\/).replaceAll(“/”)
^

So I looked into the Groovy unit tests to see how they test the replaceAll function. Unit tests are sometimes a great way to learn how to use an API. True, some unit tests can be very obscure and complex.

The unit test I found was used the ${”} GString.

So, example that Compiles:

println "new is: " +  /c:\a\b\c\d/.replaceAll((/\\${''}/),"/")
C:\temp>groovy test.groovy
new is: c:/a/b/c/d

The command line inline script could then be:

C:\temp>groovy -e "println \"new is: \" +  /c:\a\b\c\d/.replaceAll(/\\${''}/,\"/\")"
new is: c:/a/b/c/d

Ok, so it was not easier in Groovy. Maybe a Groovy expert can make it as easy?

Now, why is it so hard?

Specs
Groovy version: 1.8.1
JVM: 1.6.0_25
OS: Windows 7 64bit

Further Reading

 


Ralph Towner — Tale of Saverio

About these ads

3 Responses to Using replaceAll with Groovy regular expressions

  1. […] Using replaceAll with Groovy regular expressions « Josef’s Blog […]

  2. josefB says:

    Eric:
    I didn’t know, makes sense though, that any string could be made a regex pattern with a ~.

    Thanks for the comments.

    P.S. Can’t really use “\\” as pattern, would need “\\\\”. But, haven’t checked.

  3. As you’ve noticed, there is no way to end a slashy string with a backslash (since the slash is the only escapable character in a slashy string). If you need a long string with several backslashes, then your ${”} solution might be the best way. But if you only need one backslash, a single (or double) quote string with an escaped backslash, ‘\\’, it’s still the best solution. Either way it’s a string, and all strings (not just slashy strings) can be preceded with a ~ to make a regex pattern if needed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: