Reputation: 7025
I have written a rexeg string to parse a log into a set of groups, however it is creating an empty group when an optional section of the log is present. I have marked the section optional using ?
in regex, but it still seems to create an empty group.
Here are the two regular expressions I've tried;
([0-9]{2}:[0-9]{2}\.[0-9]{2}) - (DMG|KILL):[ ]+(.*?)\[(.*?)\] (?:damaged|killed) (.*?) \[(.*?)\](?: for (\d{0,9}) dmg)?
([0-9]{2}:[0-9]{2}\.[0-9]{2}) - (DMG|KILL):[ ]+(.*?)\[(.*?)\] (?:damaged|killed) (.*?) \[(.*?)\](?: for (\d{0,9})? dmg)?
My second regular expression has a question mark after the end of the (\d{0,9})
, as I thought there was the possibility that this was creating the empty group, but it doesn't seem to be that. I am parsing a string along the lines of the following;
00:00.00 - DMG: Player [group] damaged Victim [group] for 130 dmg
00:00.00 - KILL: Player [group] killed Victim [group]
It is when parsing the last line (no for X damage
) an empty group is created at the end.
I apologise for the monstrous regex.
It has been shown that my regular expression works fine, thanks to @Sniffer in the comments section. It can be seen here that it works as expected, however when implemented into my application, it does not.
When in my application, matcher.group(7)
(the last group) on a 'KILL' line (one that does not include 'dmg' returns null, and matcher.groupCount() returns 7 instead of 6, meaning it finds an empty group at the end. My regex is as follows;
private static final Pattern match = Pattern.compile("([0-9]{2}:[0-9]{2}\\.[0-9]{2}) - (DMG|KILL):[ \t]+(.*?)\\[(.*?)\\] (?:damaged|killed) (.*?) \\[(.*?)\\](?: for (\\d{0,9}) dmg)?");
And this is the code I am using to match the pattern;
Matcher matcher = DamageEvent.match.matcher(tLine);
if (matcher.matches())
{
int matches = matcher.groupCount();
if (matches < 6 || matches > 7)
{
System.err.println("Invalid line: " + tLine);
return null;
}
String time = matcher.group(1);
String type = matcher.group(2);
String attackerName = matcher.group(3);
String attackerGroupString = matcher.group(4);
String victimName = matcher.group(5);
String victimGroupString = matcher.group(6);
String damage = "0";
System.out.println(matches);
if (matches == 7) // This results as 'true'
{
damage = matcher.group(7); // Damage is set to null :(
}
}
Upvotes: 2
Views: 13378
Reputation: 1197
This is by design, e.g. per Javadoc:
If the match was successful but the group specified failed to match any part of the input sequence, then null is returned.
So the following example:
Matcher m1 = Pattern.compile("(t1)(t2)?(t3)").matcher("t1t3");
if(m1.matches()) {
for(int g=1;g<=m1.groupCount();g++){
System.out.println("Group "+g+": "+m1.group(g));
}
}
System.out.println("--------------");
Matcher m2 = Pattern.compile("(t1)()(t3)").matcher("t1t3");
if(m2.matches()) {
for(int g=1;g<=m2.groupCount();g++){
System.out.println("Group "+g+": "+m2.group(g));
}
}
will output:
Group 1: t1
Group 2: null
Group 3: t3
--------------
Group 1: t1
Group 2:
Group 3: t3
Upvotes: 10