正则表达式

关键字:正则表达式,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语言位操作

    #include <stdio.h> void print(int); int main(void) { int flag = 0xffe4; print(flag); printf(&q ...

  2. chromium 34以后中文字体粗体渲染问题

    估计不少人更新后都遇到这个情况了吧,粗体渲染如然变得很模糊,很奇怪,Google下说是字体实现方式变了,国内一些网站用的中文字体都是宋体,但是宋体本身没有粗体,Win下的粗体是微软自己通过某种方式实现 ...

  3. Git相关操作四

    1.克隆远程仓库 git clone remote_location clone_name remote_location为仓库地址,clone_name为要克隆到本地的仓库名称. 2.显示对应克隆地 ...

  4. ASP.NET Core 企业级开发架构简介及框架汇总

    企业开发框架包括垂直方向架构和水平方向架构.垂直方向架构是指一个应用程序的由下到上叠加多层的架构,同时这样的程序又叫整体式程序.水平方向架构是指将大应用分成若干小的应用实现系统功能的架构,同时这样的系 ...

  5. python自动化运维五:paramiko

    p { margin-bottom: 0.25cm; line-height: 120% } a:link { } paramiko是基于python实现的SSH2远程安全连接,支持认证以及密钥方式, ...

  6. RobotFrameWork安装笔记

    1.   RobotFrameWork安装配置笔记 1.1. 安装环境 64位win10家庭中文版 网上很多这方面的教程,但是比较零散,这里是自己安装配置的一个简单的笔记. 1.2. 安装说明 由于R ...

  7. 纯js实现DIV拖拽

    写代码的时候遇到需要对绝对布局的div进行拖拽的功能,起初为了省事直接在网上扒拉了一番,看到大神张鑫旭的一篇文章<JavaScript实现最简单的拖拽效果>,便直接拿来使用(膜拜大神).但 ...

  8. 使用jQuery中trigger()方法自动触发事件

    一.常用事件 在页面加载完成时  自动触发input的点击事件,在移动端可以实现自动弹出输入法,获得焦点 $("input").trigger("click") ...

  9. CSS3新增伪类汇总

    :root 选择文档的根元素,等同于 html 元素 :empty 选择没有子元素的元素 :target 选取当前活动的目标元素 :not(selector) 选择除 selector 元素意外的元素 ...

  10. JSON、JSONP、Ajax的区别

    什么是JSON JSON是一种基于文本的数据交换方式,或者叫做数据描述格式. JSON的优点: 1.基于纯文本,跨平台传递极其简单: 2.Javascript原生支持,后台语言几乎全部支持: 3.轻量 ...