Java regex parsing out middle value of String

Viewed 758

I have some data that comes in as a String, and I need to extract or print out the monthvalue ( middle group) that is in the form:

[itemvalue] [monthvalue] [yearvalue]

The rules are:

itemvalue = can be 1-3 characters (or digits) in length

monthvalue = is single alpha character [a-z]

yearvalue = can be 1, 2, or 4 digits representing calender year

Some Example Inputs:

Input1

AP18

Output1

P

Input2

QZAB19

Output2

B

Input3

ARM8

Output3

M

I was trying to compile a pattern like:

Pattern pattern = Pattern.compile("([a-zA-Z0-9]{1,3})([a-z])([0-9]{1,4})");

and then call matcher on the input to find() the groups, in this case, the monthvalue, which should be matcher.group(2) like:

Matcher m = pattern.matcher("OneOfTheExampleInputStringsFromAbove"); 

    if (matcher.find()) {
    System.out.println(matcher.group(2));
}

I thought I was close but one issue was how to include a length of 1, 2 and 4, but exclude 3 length for the yearvalue. Is my approach good? Am I missing anything in my Compile pattern?

please let me know!

4 Answers

Your regex is correct. To add your last requirement you may try:

^\w{1,3}([a-zA-Z])(?:\d{1,2}|\d{4})$
                   ^^^^^^^^^^^^^^^^
                    This part

Explanation of the above regex:

^, $ - Represents start and end of line respectively.

\w{1,3} - Matches from [0-9A-Za-z_] 1 to 3 times. If there is a chance that your test string contains _; then try to use [0-9A-Za-z] here.

([a-zA-Z]) - Represents capturing group matching a letter.

(?:\d{1,2}|\d{4}) - Represents a non-capturing group matching the digits 1, 2 or 4 times but not three.

You can find the above regex demo in here.

pictorial Representation

Implementation in java:

import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main
{
    private static final Pattern pattern = Pattern.compile("^\\w{1,3}([a-zA-Z])(?:\\d{1,2}|\\d{4})$", Pattern.MULTILINE);
    public static void main(String[] args) {
        final String string = "QZAB19\n"
     + "AP18\n"
     + "ARM8\n"
     + "ARM803"; // This won't match since the year value is 3.
     Matcher matcher = pattern.matcher(string);
     while(matcher.find())System.out.println(matcher.group(1)); // 1st group matches the month-value.
    }
}

You can find the sample run of the above code in here.

If you looking something different than a regex solution then the below could help:

String txt = "QZAB19";
String month = txt.replaceAll("[0-9]", ""); //replaces all integers
System.out.println(month.charAt(month.length()-1)); //get you the last character that is month 

Output:

B
Pattern pattern = Pattern.compile("^([a-zA-Z0-9]{1,3})([a-zA-Z])(([0-9]{1,2})|([0-9]{4}))$");

You should use $ to restrict the end matching point else your condition for restricting digts at end of string doesn't work.

Related