13

I was wondering if Java had an equivalent to C#’s named pattern matching. For example, in C# I can do something like this:

var pattern = @";(?<foo>\d{6});(?<bar>\d{6});";
var regex = new Regex(pattern , RegexOptions.None);
var match = regex.Match(";123456;123456;");

var foo = match.Groups["foo"].Success ? match.Groups["foo"].Value : null;
var bar = match.Groups["bar"].Success ? match.Groups["bar"].Value : null;

This just seems like a clean way to grab groups. Can Java do something similar, or do I need to grab groups based on index position?

String foo = matcher.group(0);
VLAZ
  • 26,331
  • 9
  • 49
  • 67
aelstonjones
  • 382
  • 2
  • 8
  • 25

3 Answers3

20

This is supported starting in Java 7. Your C# code can be translated to something like this:

String pattern = ";(?<foo>\\d{6});(?<bar>\\d{6});";
Pattern regex = Pattern.compile(pattern);
Matcher matcher = regex.matcher(";123456;123456;");
boolean success = matcher.find();

String foo = success ? matcher.group("foo") : null;
String bar = success ? matcher.group("bar") : null;

You have to create a Matcher object which doesn't actually perform the regex test until you call find().

(I used find() because it can find a match anywhere in the input string, like the Regex.Match() method. The .matches() method only returns true if the regex matches the entire input string.)

matts
  • 6,738
  • 1
  • 33
  • 50
  • 1
    Thanks for the fast reply. Unfortunately, we are still using Java 6. Maybe I'll just create an enum: String foo = matcher.group(MyGroups.FOO); – aelstonjones Jun 22 '12 at 17:36
  • 1
    Check out the [named-regexp](http://code.google.com/p/named-regexp/) project. Its specific purpose is to provide a way to handle named groups pre-Java7. – matts Jun 22 '12 at 17:39
  • 1
    The updated fork of [`named-regexp`](http://tony19.github.io/named-regexp) is preferred. – tony19 Feb 22 '14 at 05:42
  • 1
    Note that named groups will only work after calling `matcher.matches()` – bcoughlan Feb 24 '15 at 11:45
  • @bcoughlan Ah, right you are. Thanks for pointing it out. I updated the answer to include this, though I used `Matcher#find()` because it matches C#'s `Regex#Match()` method more similarly than `Matcher#matches()`. – matts Feb 24 '15 at 17:18
2

Java v1.7 now supports Perl-standard named groups like (?<name>...) and \k<name> in patterns.

You cannot have duplicate group names in the same pattern, which can be annoying in very complex cases where you are building up larger patterns out of smaller pieces out of your control. It also lacks relative indexing.

However, it should be enough for such simple things as you appear to be writing.

tchrist
  • 78,834
  • 30
  • 123
  • 180
-2

I believe you need import

org.apache.commons.lang3.StringUtils;

for this

 private Boolean validateEmail(String email)
    {
        return email.matches("^[-!#$%&'*+/0-9=?A-Z^_a-z{|}~](\\.?[-!#$%&'*+/0-9=?A-Z^_a-z{|}~])*@[a-zA-Z](-?[a-zA-Z0-9])*(\\.[a-zA-Z](-?[a-zA-Z0-9])*)+$");
    }

    private Boolean validateIP(String IP)
    {
        return IP.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
    }

    private Boolean validateHostname(String Hostname)
    {
        return Hostname.matches("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\\-]*[A-Za-z0-9])$");
    }
owen gerig
  • 6,165
  • 6
  • 52
  • 91
  • might have misunderstood the question. re-read it and now this doesnt seem like what u want. dont know what you mean by "grab groups" – owen gerig Jun 22 '12 at 17:24
  • Basically, I want a clean way to grab a matched pattern from the group array without using index numbers but a name instead. – aelstonjones Jun 22 '12 at 17:33