子组上的Java正则表达式

问题描述 投票:1回答:2

我有关于Java正则表达式的以下问题。

当我使用模式定义正则表达式时:

String pattern = "(\\d{4})\\d{2}\\d{2}";

和输入字符串是"20180808",我可以得到group(0) - 20180808

group(1) - 不匹配 group (2) - 08 group (3) - 08

我确信正则表达式可以在其他语言中有效,比如Python,C#。

有人可以帮忙吗?感谢您的专家解决方案。

@Test
public void testParseDateStringToMinimumOfTheDate() {
    try {
        UtilsFactory utilsFactory = UtilsFactory.getInstance();
        DateUtils dateUtils = utilsFactory.getInstanceOfDateUtils();
        CalendarUtils calendarUtils = utilsFactory.getInstanceOfCalendarUtils();
        calendarUtils.parseDateStringToMinimumOfTheDate("20180808");
    } catch (Exception e) {
        e.printStackTrace();
    }
} 

    public Calendar parseDateStringToMinimumOfTheDate(String dateString_yyyyMMdd) throws Exception {
    Calendar cal = null;
    String pattern = "(\\d{4})\\d{2}\\d{2}";
    try {
        cal = getMaxUtcCalendarToday();
        List<String> matchStringList = regMatch(dateString_yyyyMMdd, pattern);
        for (int i = 0; i < matchStringList.size(); i++) {

        }
    } catch (Exception e) {
        logger.error(getClassName() + ".parseDateStringToBeginningOfTheDate()- dateString_yyyyMMdd="
                + dateString_yyyyMMdd, e);
        throw e;
    }
    return cal;
}

private List<String> regMatch(String sourceString, String patternString) throws Exception {
    List<String> matchStrList = null;
    Pattern pattern = null;
    Matcher matcher = null;
    try {
        matchStrList = new ArrayList<String>();
        pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(sourceString);
        while (matcher.find()) {
            matchStrList.add(matcher.group());
        }
    } catch (Exception e) {
        logger.error(
                getClassName() + ".regMatch() - sourceString=" + sourceString + ",patternString=" + patternString,
                e);
        throw e;
    }
    return matchStrList;
}
java regex date-parsing
2个回答
2
投票
    Pattern pattern = Pattern.compile("\\d{8}");
    String sourceString = "20180808";
    Matcher matcher = pattern.matcher(sourceString);
    while (matcher.find()) {
        LocalDate date = LocalDate.parse(matcher.group(), DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(date);
    }

此代码段的输出是预期日期:

2018-08-08

如果您的字符串可能包含的文本多于8位数日期,则使用正则表达式取出这8位数字是正确的。用于日期的正确类是java.time中的LocalDate,它是现代Java日期和时间API。它是ISO日历系统中的日期,没有时间和没有时区。相比之下,Calendar代表某些日历系统中带时区的日期和时间。它远远超过你的需要。 Calendar类也很久了,并且在四年半前被java.time取代,因为它的设计很差。

如果你确实需要一个Calendar对象用于一些你无法改变或者现在不想改变的遗留API,那么转换如下:

        ZoneId zone = ZoneId.of("America/Punta_Arenas");
        ZonedDateTime startOfDay = date.atStartOfDay(zone);
        Calendar cal = GregorianCalendar.from(startOfDay);

如果没有恰好是America / Punta_Arenas,请替换正确的时区。

您的代码出了什么问题?

您的代码没有任何问题,除了它过于复杂并使用过时的日期和时间类。

    String patternString = "(\\d{4})(\\d{2})(\\d{2})";
    Pattern pattern = null;
    Matcher matcher = null;
    try {
        pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
        matcher = pattern.matcher(sourceString);
        while (matcher.find()) {
            System.out.println("group(1): " + matcher.group(1));
            System.out.println("group(2): " + matcher.group(2));
            System.out.println("group(3): " + matcher.group(3));
        }
    } catch (Exception e) {
        // TODO handle exception
        throw e;
    }

此代码段的输出是:

group(1): 2018
group(2): 08
group(3): 08

链接

Oracle tutorial: Date Time解释如何使用java.time


0
投票

你的正则表达式没有任何问题(正如你提到的(\d{4})(\d{2})(\d{2})。你做错了是,你没有正确地抓住被捕获的组。重构你的方法到这个

private static List<String> regMatch(String sourceString, String patternString) {
      List<String> matchStrList = new ArrayList<>();

      Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
      Matcher matcher = pattern.matcher(sourceString);

      if(matcher.find()) {
          for(int i = 1; i <= matcher.groupCount(); i++) {
            matchStrList.add(matcher.group(i));
          }
      }

   return matchStrList;
}

你可能想知道group 0在哪里。 Patter API捕获的组通过从左到右计算它们的左括号来编号,第一组始终是整个正则表达式。因此对于String (A)(B(C))您将获得如下组

Group 0: (A)(B(C))
Group 1: (A)
Group 2: (B(C))
Group 3: (C)

并且groupCount()方法返回匹配器模式中存在的捕获组的数量。

边注

正如@ haba713在评论中提到的那样,你可能不想只是为了解析Date来做所有这些正则表达式的麻烦。你可以简单地使用SimpleDateFormat

SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
System.out.println(formater.parse(dateString));
© www.soinside.com 2019 - 2024. All rights reserved.