Java正则表达式解析字符串中间值

4
我有一些以字符串形式输入的数据,我需要提取或打印出中间组的月份值,其格式为: [项目值] [月份值] [年份值] 规则如下: 项目值 = 长度可以是1-3个字符(或数字) 月份值 = 单个字母[a-z] 年份值 = 可以是表示日历年份的1、2或4位数字
一些示例输入: 输入1 AP18 输出1

P

输入2

QZAB19

输出2

B

输入3

ARM8

输出3

M

我试图编译一个类似的模式:
Pattern pattern = Pattern.compile("([a-zA-Z0-9]{1,3})([a-z])([0-9]{1,4})");

然后在输入上调用matcher来使用find()方法找到组,这种情况下应该是monthvalue,它应该是matcher.group(2)
Matcher m = pattern.matcher("OneOfTheExampleInputStringsFromAbove"); 

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

我以为我很接近了,但一个问题是如何在“yearvalue”中包含长度为1、2和4,但排除长度为3。我的方法好吗?在我的编译模式中有什么遗漏吗?
请告诉我!

Q:每个项目代码是否总是包括所有三个部分:itemValue、monthValue和yearValue? Q:确定itemValue的长度的规则是什么:它是一个、两个还是三个字符? - FoggyDay
是的,每个输入都有三个部分。没有确定itemvalue长度的规则,它可以是1到3个字符或数字,随机出现。这就是为什么我认为正则表达式是最好的方法。 - ennth
你可以使用或条件来排除长度为3。 - jnrdn0011
@ennth;如果以下任何答案有所帮助,请接受最适合您的答案并关闭此帖子。这将有助于回答者以及未来的读者。 - user7571182
4个回答

2
您的正则表达式是正确的。要添加您的最后一个要求,您可以尝试使用以下方法:
^\w{1,3}([a-zA-Z])(?:\d{1,2}|\d{4})$
                   ^^^^^^^^^^^^^^^^
                    This part

上述正则表达式的解释:

^, $ - 分别表示行首和行尾。

\w{1,3} - 匹配[0-9A-Za-z_] 1到3次。如果您的测试字符串中有_的可能性,请在此处使用[0-9A-Za-z]

([a-zA-Z]) - 表示匹配一个字母的捕获组。

(?:\d{1,2}|\d{4}) - 表示非捕获组,匹配数字1、2或4次,但不匹配三次。

您可以在这里找到上述正则表达式的演示。

图片表示

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.
    }
}

您可以在这里找到上述代码的样例运行。


但是\d{1,4}在yearvalue中不会捕获长度为3的内容,这违反了yearvalue规则。 - ennth
已更新正则表达式,请检查。 - user7571182

1
如果您正在寻找与正则表达式解决方案不同的内容,则以下内容可能有所帮助:
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 

输出:

B

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

你应该使用 $ 来限制匹配的结束点,否则你用于限制字符串末尾数字的条件将不起作用。

好的,这也是我想到的。你所说的在末尾加上$是什么意思?每次我看到别人在末尾加$时,他们还会在前面加^,这跟不使用^...$有什么不同呢?如果可以请您解释一下。谢谢。 - ennth
是的,您必须使用^来严格匹配起始点。我建议这样做是因为我可以看到您正在尝试匹配整个输入字符串,但如果您只想从大字符串或文件中选择匹配部分,则不需要使用^和$。 - jnrdn0011

1

但是\d{1,4}在yearvalue中不会捕获长度为3的字符吗?这违反了yearvalue规则。 - ennth
正则表达式会完成它的工作 - 它将很好地提取值。如果您还想验证潜在的错误输入...那么我建议在提取值后,在Java中检查所有可能的错误。如果您真的想排除“3”,mandy8055向您展示了如何将“或”与“非捕获子模式”结合使用。请考虑“upvoting”和“accepting”他(最优秀的!)的回复。 - FoggyDay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接