Java使用正则表达式实现重叠匹配

问题:在一篇文章中一个匹配日期yyyy-MM-dd 的程序。

显然一个日期对应Java中的正则表达式

((\\d{4})-(\\d{2})-(\\d{2}))

然而,这样的正则表达式实现方式在处理如下输入数据时,无法提取出重叠的匹配

2000-03-2401-02-2014-03-2014-02-03

结果

2000-03-24
2014-03-20

这是由于第一个匹配消耗了其所在的所有字符的缘故,后续匹配将无法使用这些字符。这是我们需要使用(?=((\\d{4})-(\\d{2})-(\\d{2}))). 正则表达式。

其中(?=X) 这个语法匹配一个“位置”,这个位置向后可以完全匹配正则表达式X。(\\d{4})-(\\d{2})-(\\d{2}) 是之前用于匹配日期的正则表达式,. 用于匹配单个字符。整个正则表达式语义为“匹配一个可以匹配日期字符串的位置及其后的一个字符”。

而原来的年月日信息可以通过groups() 函数得到——

int year = Integer.parseInt(m.group(2));
int month = Integer.parseInt(m.group(3));
int days = Integer.parseInt(m.group(4));

对应的整个程序为——

import java.util.*;
import java.util.regex.*;
import java.io.*;

class Main {
	static public void main(String args[]) throws FileNotFoundException,IOException {
		//BufferedReader fin = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		BufferedReader fin = new BufferedReader(new InputStreamReader(System.in));
		char _text[] = new char[1050];
		fin.read(_text,0,1050);
		String text = new String(_text);
		Pattern p = Pattern.compile("(?=((\\d{4})-(\\d{2})-(\\d{2}))).");
		Matcher m = p.matcher(text);
		boolean flag = false;
		while (m.find()) {
			int year = Integer.parseInt(m.group(2));
			int month = Integer.parseInt(m.group(3));
			int days = Integer.parseInt(m.group(4));
			if (year < 1990 || year>=2018)
				continue;
			if (days <= 0)
				continue;
			if (month < 1 || month > 12)
				continue;
			if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
				if (days > 31)
					continue;
			if (month == 4 || month == 6 || month == 9 || month == 11)
				if (days > 30)
					continue;
			if (month == 2)
				if (days > 28)
					continue;
			System.out.println(m.group(1));
			flag = true;
		}
		if (!flag)
			System.out.println("NotMatch");
	}
};

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据