正则表达式

关键字:正则表达式,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. C#实现局域网内远程开机

    1.远程开机原理 远程开机Wake on LAN(WOL),俗称远程唤醒,远程唤醒的实现主要是向目标主机发送特殊格式的数据包,是AMD公司制作的MagicPacket这套软件以生成网络唤醒所需要的特殊 ...

  2. (转)关于Tomcat的点点滴滴(体系架构、处理http请求的过程、安装和配置、目录结构、设置压缩和对中文文件名的支持、以及Catalina这个名字的由来……等)

    转自:http://itfish.net/article/41668.html   总结Tomcat的体系架构.处理http请求的过程.安装和配置.目录结构.设置压缩和对中文文件名的支持.以及Cata ...

  3. Windows7搭建Wamp环境

    wamp:Windows + Apache + MySQL + PHP 首先,在D盘根目录下新建目录wamp,wamp下建目录www和bin,www目录作为网站文件入口目录,bin下建目录Apache ...

  4. 游标的小知识(借鉴and整理)

    一.游标(用来存储多条查询数据的一种数据结构(结果集),它有一个指针,用来从上往下移动,从而达到遍历每条记录的作用) 游标也可以理解为逐行返回SQL语句的结果集 如何编写一个游标? 1.声明游标 de ...

  5. JS框架设计读书笔记之-函数

    这次写一些函数 1.模拟Object.keys方法 Object.keys = Object.keys || function(obj){ var a = []; // a[0],a[1]...分别赋 ...

  6. StringDup(理论AC)

    Problem Statement for StringDup Problem Statement      Create a class called StringDup. Given a stri ...

  7. 不怕你配置不对,就怕你看的资料不对!MIM 与 SharePoint 同步完全配置指南。

    为了更好的同步 User Profile,在 SharePoint 2010 中首次引入了 FIM (ForeFront Identity Manager) 用于编辑 User Profile 的同期 ...

  8. 利用echarts highcharts 实现自定义地图 关系图效果 侧边3D柱形图饼图散点图

    github 地址:  https://https://github.com/Gengshaoxuan/medataMap github 地址:  https://https://github.com ...

  9. 按键(vb)启动指定目录的程序以及获取当前应用路径

    Private Declare Function GetDesktopWindow Lib "user32" () As Long Private Declare Function ...

  10. Java 核心内容相关面试题【1】

    1.什么是 transient 变量? transient 变量是指不会被序列化的变量. 2.什么是同步(synchronization)? 在多线程环境中,同步是指控制多个线程访问共享资源的方式.没 ...