knorv
knorv

Reputation: 50127

Groovy syntax for regular expression matching

What is the Groovy equivalent of the following Perl code?

my $txt = "abc : groovy : def";
if ($txt =~ / : (.+?) : /) {
  my $match = $1;
  print "MATCH=$match\n"; 
  # should print "MATCH=groovy\n"
}

I know that there's more than one way to do it (including the regular Java way) - but what is the "Groovy way" of doing it?

This is one way of doing it, but it feels a bit clumsy - especially the array notation (m[0][1]) which feels a bit strange. Is there a better way do it? If not - please describe the logic behind m[0][1].

def txt = "java : groovy : grails"
if ((m = txt =~ / : (.+?) :/)) {
  def match = m[0][1]
  println "MATCH=$match"
}

Upvotes: 60

Views: 94031

Answers (4)

Joman68
Joman68

Reputation: 2850

Be aware that if you want to use the group() method to retrieve the group match, the match code needs to be put into a conditional.

Take this code:

def subject = "CN=mycn,[email protected]"
if (match1 = subject =~ /CN=(.*?),.*/) {
    println match1.group(1)
}

def match2 = subject =~ /CN=(.*?),.*/
println match2.group(1)

The output of running the above code (in Groovy 3.09, JVM 17.0.1) is:

mycn

Caught: java.lang.IllegalStateException: No match found
java.lang.IllegalStateException: No match found
    at java_util_regex_MatchResult$group.call(Unknown Source)
    at jdoodle.run(jdoodle.groovy:7)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

So match1.group(1) succeeds and returns the correct match mycn.

match2.group(1) results in an IllegalStateException.

So the match instance is only fully evaluated inside the conditional.

Upvotes: 1

knorv
knorv

Reputation: 50127

This was the closest match to the Perl code that I could achieve:

def txt = "abc : groovy : def"
if ((m = txt =~ / : (.+?) : /)) {
  def match = m.group(1)
  println "MATCH=$match"
}

// Prints:
// MATCH=groovy

Upvotes: 29

Chas. Owens
Chas. Owens

Reputation: 64939

m[0] is the first match object.
m[0][0] is everything that matched in this match.
m[0][1] is the first capture in this match.
m[0][2] is the second capture in this match.

Based on what I have read (I don't program in Groovy or have a copy handy), given

def m = "barbaz" =~ /(ba)([rz])/;

m[0][0] will be "bar"
m[0][1] will be "ba"
m[0][2] will be "r"
m[1][0] will be "baz"
m[1][1] will be "ba"
m[1][2] will be "z"

I could not stand not knowing if I was correct or not, so I downloaded groovy and wrote an example:

def m = "barbaz" =~ /(ba)([rz])/;

println "m[0][0] " + m[0][0]
println "m[0][1] " + m[0][1]
println "m[0][2] " + m[0][2]
println "m[1][0] " + m[1][0]
println "m[1][1] " + m[1][1]
println "m[1][2] " + m[1][2]

Upvotes: 110

C. K. Young
C. K. Young

Reputation: 223183

This is my best understanding of how to do this using Groovy syntax (but see lfaraone's response too):

import java.util.regex.Matcher

def txt = 'abc : groovy : def'
if (txt =~ ~/ : (.+?) : /) {
    def match = Matcher.lastMatcher[0][1]
    println "MATCH=$match"
}

Upvotes: 1

Related Questions