正则表达式

关键字:正则表达式,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程序员懂你的更多相关文章

  1. PHP笔记——java程序员看懂PHP程序

    PHP笔记——java程序员看懂PHP程序   php是一种服务器端脚本语言,类型松散的语言. <?php   ?>       xml风格 <script language=”ph ...

  2. [转载]一个标准java程序员的进阶过程

    第一阶段:Java程序员 技术名称 内                 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...

  3. Java 程序员们值得一看的好书推荐

    "学习的最好途径就是看书",这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一 ...

  4. Java程序员应该掌握的10项技能

    这篇文章主要介绍了作为Java程序员应该掌握的10项技能,包括java的知识点与相关的技能,对于java的学习有不错的参考借鉴价值,需要的朋友可以参考下   1.语法:必须比较熟悉,在写代码的时候ID ...

  5. Java程序员学习之路

    1. Java语言基础 谈到Java语 言基础学习的书籍,大家肯定会推荐Bruce Eckel的<Thinking in Java>.它是一本写的相当深刻的技术书籍,Java语言基础部分基 ...

  6. 分享下对JAVA程序员成长之路的总结<转>

    我也搞了几年JAVA了,由于一向懒惰,没有成为大牛,只是一普通程序猿,手痒来给新人分享下从新手成长为老鸟的已见.   首先初识语法的阶段,必须要学会怎么操作对象,操作if和for,操作list set ...

  7. 谈谈Java程序员进阶的那些知识和方向

    谈谈Java程序员进阶的那些知识和方向 记得前段时间看过一篇文章谈到一种程序员叫野生程序员,战斗力极强,可以搞定一切问题,但是通常看问题抓不到本质,或者说是google/baidu/stackover ...

  8. 转载:java程序员如何拿到2万月薪

    作者:匿名用户链接:https://www.zhihu.com/question/39890405/answer/83676977来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  9. Java 程序员们值得一看的好书推荐[转载]

    “学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超其他 ...

随机推荐

  1. 【ASP.NET MVC 学习笔记】- 02 Attribute

    本文参考:http://www.cnblogs.com/willick/p/3208427.html 1.特性(Attribute)对程序中的元素进行标注,比如类.字段.方法.属性等. 2.在.NET ...

  2. LeetCode 581. Shortest Unsorted Continuous Subarray (最短无序连续子数组)

    Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...

  3. mac上使用crontab周期性执行python脚本

    这个月买了本书<Linux系统命令及Shell脚本实践指南>, 看到了一个周期性执行任务cron.顿时产生一个想法: mac上有这种机制么? 加上自己也在15年下半年也学了点python脚 ...

  4. ES6 class的继承使用细节

    ES6 class的继承与java的继承大同小异,如果学过java的话应该很容易理解,都是通过extends关键字继承. class Animal{ constructor(color){ this. ...

  5. windows 系统下C++实现的多线程

    摘抄http://blog.csdn.net/huyiyang2010/article/details/5809919 Thread.h #ifndef __THREAD_H__ #define __ ...

  6. Can you solve this equation?

    Problem Description Now,given the equation 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,can you find its sol ...

  7. 【Spring】渲染Web视图

    前言 前面学习了编写Web请求的控制器,创建简单的视图,本篇博文讲解控制器完成请求到结果渲染到用户的浏览器的过程. 渲染Web视图 理解视图解析 前面所编写的控制器方法都没有直接产生浏览器中渲染所需要 ...

  8. 附录三 关于book.h

    本书中用到的公用函数放到了头文件book.h中. #ifndef __BOOK_H__ #define __BOOK_H__ #include <stdio.h> #include < ...

  9. SSH框架的多表查询和增删查改 (方法一)中

    原创作品,允许转载,转载时请务必标明作者信息和声明本文章==>http://www.cnblogs.com/zhu520/p/7774144.html   这边文章是接的刚刚前一遍的基础上敲的  ...

  10. 基于node的websocket示例

    websocket:用语服务器端主动向客户端推送消息 本例基于koa框架编写用例:服务器端需要安装相关模块 koa koa-socket co等 服务器端脚本:(需要安装相关模块 koa koa-so ...