正则表达式——Java程序员懂你
正则表达式
关键字:正则表达式,Pattern,Matcher,字符串方法,split,replace
前文书立下了一个flag,这里要把它完成,就是正则表达式,它是一个工具,是很早就存在于标准Unix工具集之中的,例如sed和awk。然而不经常使用Unix系统的程序员们依然能够在JavaScript,java,python,perl等等地方看到它,每当我们看到手指纷飞的他人写着精妙的一小撮正则就干了我们好几篇的校验代码的时候,心里默默升起一股羡慕之情,同时只能赶紧把这一小撮正则保存下来,下次好修修补补继续用,那么,我们能否读懂正则表达式呢,不再把它们作为天书看待。
Java程序员普遍对与正则表达式并不算深入,因为我们有String以及StringBuilder,我们引以为傲的强大的java的字符串的处理在正则表达式的面前只能是小垃。
正则表达式是一种强大灵活的文本处理工具,通过它能够解决各种字符串处理相关的问题:匹配、选择、编辑以及验证,Java程序员们,扔掉split(),replace()以及subString()吧,每次通过他们的组合变来变去只为了实现一个我们不到一首诗的时间的需求,简直对计算机和对我们本人来讲都是一种消耗。
一、热身
首先介绍几个最基础的正则表达式热热身。
- 正则表达式使用反斜杠\来转义特殊字符,java中使用两个反斜杠\\
- ?: 一个或者没有
- +: 一个或者多个
- \d: 数字
- (): 用括号分组,整体相当于一个单独的字符
- |: 代表或者,一般与括号分组一起使用
下面看具体代码,
测试方案
这里的测试方案是采用的之前io中文件名过滤器的那段代码。首先我们定义一个字符串数组作为源数据。
String[] data = { "a.txt", "+", "12345", "8", "-2", "-2123", "+010" };
这些字符串中基本包含了我们以下要练手的内容。接着,定义一个简单的获取数字的正则。
String regExp = "\\d";// 一位数的正整数字符【只匹配一个】
然后下面使用这个正则的方式为:
for (String s : data) {
if (Pattern.matches(regExp, s))
logger.info(s);
}
意思为遍历字符串数组,如果匹配了该正则表达式,则打印出来(这里只做一个测试方案,具体Pattern以及Matcher在下面会有详细介绍)。这段代码的输出结果为:
09:21:02[testRegExp]: 8
开始测试
上面的测试方案中我们写入的正则表达式是“\\d”,只匹配一位正整数字符。下面开始正式热身测试。
regExp = "\\d+";// 正数数字【加号+代表一个或者多个】
09:33:48[testRegExp]: 12345
09:33:48[testRegExp]: 8
regExp = "-?\\d+";// 数字(包括正数和负数)
09:34:27[testRegExp]: 12345
09:34:27[testRegExp]: 8
09:34:27[testRegExp]: -2
09:34:27[testRegExp]: -2123
regExp = "-\\d+";// 所有负数【只匹配以一个字符‘-’开头的】
09:34:49[testRegExp]: -2
09:34:49[testRegExp]: -2123
regExp = "-\\d";// 只有一位数的负数【只匹配以一个字符‘-’开头的,同时只有一位整数的字符串】
09:35:06[testRegExp]: -2
从上面这四段正则可以总结出来,假设有一个字符a,我们匹配它各种情况的正则表达式的方式为:
a?(一个或者没有) -> a(只有一个) -> a+(一个或者多个)
regExp = "\\+";// 内容为加号的字符串
09:37:21[testRegExp]: +
regExp = "\\+\\d+";// 以加号开头接整数的字符串
09:37:59[testRegExp]: +010
这两段的意思是我们要匹配加号,但加号本身又是正则表达式的一部分运算符,所以要加\\来将其转义为普通字符。
regExp = "(\\+|-)\\d+";// 以一个加号或者一个负号开头的数字
09:39:29[testRegExp]: -2
09:39:29[testRegExp]: -2123
09:39:29[testRegExp]: +010
regExp = "(\\+|-)?\\d+";// 以一个加号或者一个负号开头或者没有符号的数字
09:39:47[testRegExp]: 12345
09:39:47[testRegExp]: 8
09:39:47[testRegExp]: -2
09:39:47[testRegExp]: -2123
09:39:47[testRegExp]: +010
这两段我们使用了括号用来表示一个分组,整个括号内容相当于一个单独的字符。
String方法中的正则表达式
上面提到过java字符串中的split,replace等方法,他们是支持正则表达式的,所以不要只用他们的字符串简单操作,划分替换的部分,还可以应用一下正则表达式,正则表达式给了我们编程上一个模糊查询的作用,对比起来直接使用字符串本身作为搜索参数,一个正则表达式可以代表的内容更加丰富。
- split方法
String regex = " ";// 按空格来划分字符串
regex = "\\W+";// 正则选择出非单词字符,split过滤一遍以后剩下纯单词,删除其他符号
regex = "g\\W+";// 字母n后面跟着非单词字符,也就是‘n后面有空格字符’,split以后就去掉了n和这个空格
String preface = "I wish I had this book when I started programming... I recommend this book to every student as well as beginner and intermediate Java programmer.";
String[] a = preface.split(regex);
logger.info(a.length + " " + Arrays.toString(a));
11:03:17[testSplit]: 2 [I wish I had this book when I started programmin, I recommend this book to every student as well as beginner and intermediate Java programmer.]
- replace方法
logger.info(preface.replaceFirst("p\\w+", "heyhey"));// 将第一个p打头的单词改为heyhey
logger.info(preface.replaceAll("p\\w+", "heyhey"));// 将全部p打头的单词改为heyhey
11:03:17[testSplit]: I wish I had this book when I started heyhey... I recommend this book to every student as well as beginner and intermediate Java programmer.
11:03:17[testSplit]: I wish I had this book when I started heyhey... I recommend this book to every student as well as beginner and intermediate Java heyhey.
具体解释请直接看代码中的注释。
二、java.util.regex
前面的正则表达式都是一个字符串对象,然而java支持了专门的更加强大的正则表达式相关的类。下面来介绍如何在java中创建一个正则表达式,主要是在java.util.regex中的Pattern类和Matcher类。
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
logger.info(b);
输出:true
如果不涉及模式重用、匹配器重用,可以改为
logger.info(Pattern.matches("a*b", "aaaab"));
11:22:59[testRegex]: true
上面介绍过?,无符号和+,分别代表一个或没有,一个,一个或多个,那么有没有一个符号可以覆盖它们所有情况,代表没有或有,一个或多个呢?
- *: 含有一个或多个该字符,或者不含有该字符
而且一般正则表达式是小写字母代表本身意思,它的大写代表相反的意思,例如上面提到的,
- \w: 词字符,大小写字母加数字
- \W: 非词字符
- ^: 非
所以\W也可以表示为[^\w],同样的,
- \d: 匹配数字[0-9]
- \D: 非数字[^0-9]
- []: 方括号,表示其中的任意字符,相当于括号加|的分组
- \s: 空白符(空格、tab、换行、换页或回车)
- \S: 非空白符[^\s]
接着,再说几种方括号内部的情况,
- [abc]: 包含abc任意字符的单个字符(注意只有一个字符)
Pattern p = Pattern.compile("[abc]");
logger.info(p.matcher("abc").matches());
logger.info(p.matcher("b").matches());
logger.info(p.matcher("ab").matches());
logger.info(p.matcher("c").matches());
14:15:57[testRegex]: false
14:15:57[testRegex]: true
14:15:57[testRegex]: false
14:15:57[testRegex]: true
[abc]与(a|b|c)的效果是相同的。
- [a-zA-Z]: 同样是单个字符,字符范围是大小写字母。
方括号如果不加?,*或者+,效果与无符号的单个字符一样,代表仅匹配一个字符。
- [abc[hij]]: 同样是匹配单个字符,范围是abchij,并集。
- [a-z&&[hcj]]: 取的是交集,hcj在a-z的范围内,所以最终意思为匹配一个字符,字符范围在hcj任意一个。
数量的设定
正则表达式可以约定字符出现的次数,上面的?,*,+都已经提到了,那么具体的量词如何设置呢?
Pattern p = Pattern.compile("[a-z]{3}");
logger.info(p.matcher("abc234").matches());
logger.info(p.matcher("ccc").matches());
logger.info(p.matcher("ab").matches());
logger.info(p.matcher("c").matches());
15:12:49[testRegex]: false
15:12:49[testRegex]: true
15:12:49[testRegex]: false
15:12:49[testRegex]: false
总结
本文介绍的正则表达式内容比较入门,但是对于java程序员处理常见问题已经够用,尤其是读懂已有代码,修修补补的能力应该是有的。
正则表达式——Java程序员懂你的更多相关文章
- PHP笔记——java程序员看懂PHP程序
PHP笔记——java程序员看懂PHP程序 php是一种服务器端脚本语言,类型松散的语言. <?php ?> xml风格 <script language=”ph ...
- [转载]一个标准java程序员的进阶过程
第一阶段:Java程序员 技术名称 内 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...
- Java 程序员们值得一看的好书推荐
"学习的最好途径就是看书",这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一 ...
- Java程序员应该掌握的10项技能
这篇文章主要介绍了作为Java程序员应该掌握的10项技能,包括java的知识点与相关的技能,对于java的学习有不错的参考借鉴价值,需要的朋友可以参考下 1.语法:必须比较熟悉,在写代码的时候ID ...
- Java程序员学习之路
1. Java语言基础 谈到Java语 言基础学习的书籍,大家肯定会推荐Bruce Eckel的<Thinking in Java>.它是一本写的相当深刻的技术书籍,Java语言基础部分基 ...
- 分享下对JAVA程序员成长之路的总结<转>
我也搞了几年JAVA了,由于一向懒惰,没有成为大牛,只是一普通程序猿,手痒来给新人分享下从新手成长为老鸟的已见. 首先初识语法的阶段,必须要学会怎么操作对象,操作if和for,操作list set ...
- 谈谈Java程序员进阶的那些知识和方向
谈谈Java程序员进阶的那些知识和方向 记得前段时间看过一篇文章谈到一种程序员叫野生程序员,战斗力极强,可以搞定一切问题,但是通常看问题抓不到本质,或者说是google/baidu/stackover ...
- 转载:java程序员如何拿到2万月薪
作者:匿名用户链接:https://www.zhihu.com/question/39890405/answer/83676977来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- Java 程序员们值得一看的好书推荐[转载]
“学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超其他 ...
随机推荐
- mybatis generator eclipse插件的安装
mybatis generator 可以提高开发速度,这个插件可以自动生成代码,创建DAO层相关代码,就像利用HIbernate反相生成一样,安装前可以先到百度网盘下载: 文件:MyBatisGene ...
- HandlerThread学习
之前基本讲过Handler的一些知识了,我们今天学习下Google封装的一个实现线程通信的一个类HandlerThread 一.HandlerThread使用 @Override protected ...
- angular核心$watch,$digest,$apply之间的联系
浏览器事件发生时,会在浏览器的上下文window中执行,而angular有自己的上下文angular content,angular 事件在自己的上下文angular content中执行. $wat ...
- 前端菜鸟学习之DOM事件处理
一.事件处理程序 1.DOM0级事件处理程序:就是将一个函数赋值给一个事件处理程序属性,至今仍为现代所有浏览器所支持,主要得益于其跨浏览器的优势,要使用DOM0级事件 首先要得到操作对象的引用,具体实 ...
- rsync 服务部署详解
第1章 rsync 软件介绍 1.1 什么是rsync rsync 是一款开源的.快速的.多功能的.可实现全量及增量的本地或远程数据同步备份的优秀工具. http://www.samba.org/ft ...
- Python入门学习(一)
看完了莫烦Python的视频,对于Python有了一点感觉,接下来打算把小甲鱼的视频啃完,附上学习网址:http://blog.fishc.com/category/python 小甲鱼的视频是从零基 ...
- AngularJS学习篇(二十三)
AngularJS 路由 AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 通过 AngularJS 可以实现多视图的单页Web应用(single page web applica ...
- Cache 和 Buffer 都是缓存,主要区别是什么?
存储器的高速缓冲存储器存储了频繁访问的RAM位置的内容及这些数据项的存储地址.当处理器引用存储器中的某地址时,高速缓冲存储器便检查是否存有该地址.如果存有该地址,则将数据返回处理器;如果没有保存该地址 ...
- Js的闭包,这篇写的是比较清晰明了的
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- spring返回@ResponseBody报406
HTTP Status 406 - type Status report message description The resource identified by this request is ...