最近在论坛里问正则表达式的特别多,我对这方面了解的也不是很多,也就是顺便学习学习。还是引用论坛里的一个问题吧:如何将下面这段字符串分离出IP地址,连接时间和链接。
- Stringstr="doctor_access_log.1177977600:65.55.210.14--[01/May/2007:00:00:26-0500]\"GET/estil.strawnHTTP/1.0\"4041400671.86.225.114--[23/May/2007:11:39:29-0500]\"GET/healthlink.cssHTTP/1.1\"2001799";
凭观察我们能发现这个字符串里的IP有:65.55.210.14和71.86.225.114;连接时间有01/May/2007:00:00:26 -0500和23/May/2007:11:39:29 -0500; 链接有/estil.strawn HTTP/1.0和/healthlink.css HTTP/1.1。而且连接时间和链接有两个很明显的特征就是分别在"[]"和""""之间。下面来具体看看如何一一匹配。先来看如何匹配IP地址,这里只针对于IP V4的32bit的地址,他们都有一个共同的特征就是有4个字节,每个字节的十进制数是由[0-9]组成的(废话!),每个字节间都有"."分割。都知道在正则表达式中,\\d和[0-9]可以来表示数字;匹配的次数都是用量词(quantifier)来表示的,比如*或者+,也可以用具体的次数,比如{m,}就是表示最少匹配m次,{m,n}表示匹配m到n次。那么这样就能很容易的写出匹配IP的正则表达式了:
- Stringregex="\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}";
当然了你也可以再仔细观察一下,其实IP地址的前3个字节和“.”都可以写在一起:
- Stringregex="(\\d{1,3}\\.){3}\\d{1,3}";
再看看如何匹配连接时间的匹配吧,有了前面的经验,自然知道挨个的去匹配:
- Stringregex="\\d{2}/[A-Z][a-z]+/\\d{4}:\\d{2}:\\d{2}:\\d{2}\\s-\\d{4}";
但是仔细观察还是可以利用我们前面提到的一个特点,就是在"["开始之后,只要没有遇到"]",那么这之前的都是属于时间的。如果这么理解的话,表达式就可以写的很简洁了:
- Stringregex="[^\]]+";
好了有了上面的经验,那么写起匹配链接的正则表达式就会容易的多了:
- Stringregex="/[^\"]+";
那么现在就可以合并起来了,这个的代码如下:
- importjava.util.regex.*;
- publicclassLogAnalyze{
- publicstaticvoidmain(Stringargs[]){
- Stringstr="doctor_access_log.1177977600:65.55.210.14--[01/May/2007:00:00:26-0500]\"GET/estil.strawnHTTP/1.0\"4041400671.86.225.114--[23/May/2007:11:39:29-0500]\"GET/healthlink.cssHTTP/1.1\"2001799";
- Stringregex="(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\s-\\s-\\s\\[([^\\]]+)\\]\\s\"GET\\s(/[^\"]+)\"\\s";
- Patternpattern=Pattern.compile(regex);
- Matchermatcher=pattern.matcher(str);
- while(matcher.find()){
- System.out.println("IP:\n"+matcher.group(1));
- System.out.println("Time:\n"+matcher.group(2));
- System.out.println("Site:\n"+matcher.group(3)+"\n");
- }
- }
- }
运行的结果是:
- IP:
- 65.55.210.14
- Time:
- 01/May/2007:00:00:26-0500
- Site:
- /estil.strawnHTTP/1.0
- IP:
- 71.86.225.114
- Time:
- 23/May/2007:11:39:29-0500
- Site:
- /healthlink.cssHTTP/1.1
当然了,你也可以把那一个正则表达式分开写,然后依次匹配出IP地址,连接时间和链接。