java利用format实例去充_正则表达式的学习入门实例(java篇)

从6月起,做了很长一段时间的讲座信息的自动抓取工作,其中最主要依赖的便是需要一个特别棒的时间解析引擎,希望能够尽可能多地解析各种格式的时间和数据,可惜真心找不到太好的“轮子”,为此不得不花比较多的时间来处理和解析时间字符串,java在text包中提供了DateFormat接口和SimpleDateFormat确实让问题稍微简单了一些,不过但凡做过时间处理的同学都清楚,只是“稍微简单”而已。为了做这样一个通用的时间字符串解析方法,自己也走了不少弯路,在经过一个月后的摸索发现,真正能够帮助解决问题的还是 java的正则表达的引擎,在策略上则是尽可能让字符串经过正则表达的处理,最终转换为统一的一个或两个主要格式,也就是在这个认识奠定之后,明确了正则表达式的重要性——而之前真的只是书本知识罢了。

《精通正则表达式 》的序言中,曾经写道如果罗列计算机软件领域的伟大发明,也不会超出二十项,包括分组交换网络、Web、Lisp、哈希算法、UNIX、编译技术、关系模型、面向对象、XML这些大名鼎鼎的家伙,而正则表达式绝对不应该被漏掉。在后面的正则的使用体会当中,序言当中说到“对于很多的实际工作来讲,正则表达式简直是灵丹妙药,能够成百倍地提高开发效率和程序质量”,正则表达式最为经典的使用则是在生物信息学和人类基因图谱的研究。

结合自己最近为实现讲座信息的自动解析而不得不做的时间解析引擎的体会,正则表达式绝对是任何程序语言用来处理字符串的利器,有了它能够大幅提高程序开发效率,如果没有使用正则或者没有充分应用到合适的正则高级特性,很多的程序代码无疑是繁琐而蹩脚的,不管是写程式的当事人还是后来的维护者,面对大量底层的字符串的切割、拼接和数组操作都会非常郁闷,笔者在刚开始做的时间解析的时候就有若干个方法不得不用String的split方法不停地拼接(因为当时确实未掌握正则表达的高级特性)。

OK,以上这些无疑都可以归纳为一句话,powerful regular expresstions, which need programmer to master and apply to your work ,强大的正则在字符串处理的时候应该是程序员的第一反应。接下来主要该讨论的则是如何具体地学习掌握和熟练使用java 的正则表达式(因笔者只用java)。

想要真正学习使用正则表达式,一个必不可少的过程就是在一个个的实例的问题解决当中不断进阶,随着问题从简单到复杂,对正则语法的掌握也便从简单到高级进阶。

《精通正则表达式》这本书写的不错,不过对于java程序员而没有Perl/ PHP/.NET语法不懂的话,实在可惜了,没有办法能够看懂其中高级特性当中针对非java语言的具体实例,所以客观上影响了使用java正则表达式运用高级特性学习,同时也是作为自己从正则使用的初学者更高层进阶的过程,写这样的一篇博文来总结提高。

案例1:利用java正则的捕获组定向提取满足逻辑需要的某一特定字符串段块

具体将字符串The population of 2984444215 is growing当中的具体population值提取出来

要解决这个问题,需要的主要是java基本的正则语法和相关两个主要类java.util.regex.Pattern和java.util.regex.Matcher的掌握,属于最为简单的任务。

这里有两种解决思路,针对这个字符串

第一种,只利用\d+匹配字符串当中出现的字符串,如果要提取的2984444215这个数字串之外再也没有其他数字,则可以使用这样粗糙的方法。

具体实现方法如下

String str="The population of 2984444215 is growing";

Pattern p=Pattern.compile("\\d+");

Matcher m=p.matcher(str);

if(m.find()){

String result=m.group();

System.out.println("result is "+result);

}

第二种,更加精确一些。判定是一连串数字,而这一连串的数字满足的特性就是前面的字符串一定是population of,其实也就是匹配population of XXX这个逻辑组块当中的XXX,而且XXX一定是连续的数字才行

,可以使用单纯的正则表达的捕获组来做,也可以使用高级特性部分的逆向环视完成,用捕获组解决的代码如下

String str="The population of 2984444215 is growing";

Pattern p=Pattern.compile(".*(population\\s+of\\s+)(\\d+).*");

Matcher m=p.matcher(str);

if(m.find()){

String result=m.group(2); //采用正则的捕获组,确保字符串的位置正确

System.out.println("result is "+result);

}

案例2:利用java正则将满足逻辑需要的多个字符串段块提取出来

举例:利用java正则将如下文本当中的population的系列值全部提出取出

The population of China is 1295000000

The population of Japan is 135000000

案例3:

运用组(group) 对字符串当中的逻辑组块进行位置的前后转换和调整,具体设计到正则表达的分组、反向引用的知识。

实现目标:将2012-8-17,9:30-11:30转换为9:30-11:30,2012-8-17 ,其实就是一个简单的位置颠倒的工作

实现手段可以有至少两种,第一种是使用硬性的字符串切割、拼接的思路,比如可以用,将字符串切割为两个部分,然后将其重新用+弄在一块,这样的代码实现如下。

另一种就是使用正则表达式,通过一行代码就可以搞定,代码实现如下

String str="2012-8-17,9:30-11:30";

str=str.replaceAll("(\\d{4}-\\d{1,2}-\\d{1,2}),(\\d{1,2}:\\d{1,2}-\\d{1,2}:\\d{1,2})",

"$2,$1");

System.out.println(str);

案例4:

将时间字符串10:00-11:30 AM, Tuesday, May 22nd,2011当中的22nd转换为22,也就是将21st中的st 22nd的nd和23rd的rd以及24th的th去掉,

这个问题的解决相对来说就比较棘手,因为单纯的使用String的replace(“nd”,””)方法的话,会同时将Monday或Sunday当中的nd给替换掉,也就是笼统地使用替换将nd给去掉,会干扰到其他的含有nd字符串,因此不得不首先排除掉其他字符串都没有nd这样的字符,事情就会麻烦很多。

具体的针对nd的情况,其实正则表达式提供的环视功能(lookaround)包括顺序环视和逆序环视,在这里使用逆序环视的功能就能够解决,如果确保nd之前一定是以2结尾的数字(比如2,232)那么对于这种情况的nd的替换就是我们想要的,所以就可以确保不会替换Sunday当中的nd

具体实现的代码方法如下,其实做的还是有待进一步精确,只是说够用了

public static String handleStNdRdTh(String str){

String result=str;

Pattern p1=Pattern.compile("\\d{1,2}st");

Pattern p2=Pattern.compile("\\d{1,2}nd");

Pattern p3=Pattern.compile("\\d{1,2}rd");

Pattern p4=Pattern.compile("\\d{1,2}th");

Matcher m=p1.matcher(str);

if(m.find()){

String tmp=m.group();

String numbStr="";

Pattern p=Pattern.compile("\\d{1,2}");

Matcher m2=p.matcher(tmp);

if(m2.find()){

numbStr=m2.group();

result=str.replace(tmp,numbStr);

}

}else if(m.reset().usePattern(p2).find()){

String tmp=m.group();

String numbStr="";

Pattern p=Pattern.compile("\\d{1,2}");

Matcher m2=p.matcher(tmp);

if(m2.find()){

numbStr=m2.group();

result=str.replace(tmp,numbStr);

}

}else if(m.reset().usePattern(p3).find()){

String tmp=m.group();

String numbStr="";

Pattern p=Pattern.compile("\\d{1,2}");

Matcher m2=p.matcher(tmp);

if(m2.find()){

numbStr=m2.group();

result=str.replace(tmp,numbStr);

}

}else if(m.reset().usePattern(p4).find()){

String tmp=m.group();

String numbStr="";

Pattern p=Pattern.compile("\\d{1,2}");

Matcher m2=p.matcher(tmp);

if(m2.find()){

numbStr=m2.group();

result=str.replace(tmp,numbStr);

}

}

return result;

}

案例5:指定位置插入字符串或指定位置删除字符串

实现目标:将The population of 2984444215 is growing当中的数字实现从右到左每3个数字就添加一个逗号

这个例子其实也是《精通正则表达式》当中的具体实例,只不过是具体采用Perl这门语言实现,同时解决方案也是有多种。第一种是最笨的办法,首先将字符串当中连续的数字字符串给取出来,然后将字符串每3个划分,然后逐个地再拼接起来;第二种是采用正则表达式的环视功能来解决,根据使用的环视的不同又分为顺序环视和逆序环视两种不同的实现。

具体的实现代码如下:

逆序环视——

String testStr="The population of 2984444215 is growing";

//利用逆向环视功能,非数字字符的结尾

testStr=testStr.replaceAll("(?<=\\d)(?=(\\d\\d\\d)+(?!\\d))",",");

System.out.println(testStr);

顺序环视——

String testStr="The population of 2984444215 is growing";

//利用正向环视功能,还有用到了反向引用

testStr=testStr.replaceAll("(\\d)(?=(\\d\\d\\d)+(?!\\d))","$1,");

System.out.println(testStr);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值