关于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;
}
答案 0 :(得分: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(现代Java日期和时间API)中的LocalDate
。这是ISO日历系统中的日期,没有日期和时区。相比之下,Calendar
表示某些日历系统中带有时区的日期和时间。远远超出您的需要。此外,Calendar
类已经过时了,并且由于设计不佳而在四年半之前被java.time取代。
如果您确实需要Calendar
对象来处理一些您无法更改或暂时不想更改的旧版API,请按以下方式进行转换:
ZoneId zone = ZoneId.of("America/Punta_Arenas");
ZonedDateTime startOfDay = date.atStartOfDay(zone);
Calendar cal = GregorianCalendar.from(startOfDay);
如果不是美国/蓬塔阿雷纳斯,请替换正确的时区。
您的代码没有什么问题,除了它过于复杂并且使用过时的日期和时间类别。
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
。
答案 1 :(得分: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捕获的组通过从左到右计数它们的左括号来编号,并且第一组始终是整个正则表达式。因此,对于字符串(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));