正则表达式

概述

正则表达式是专门用来做字符串操作的一种工具,它主要提供了四种功能:文本匹配,文本提取,文本替换, 字符串拆分;后两种功能都是基于第一种功能之上做出来的扩展;文本匹配主要通过正则表达式中的各种定位符和字符匹配符来实现的;文本提取是根据第一种功能另外加上分组来实现的;文本替换是使用前两种功能来增强字符串替换功能。先做一个简短的关于正则表达式能做什么的介绍,更详细的内容在下面介绍。
下面是我在工作中做一些体力活的时候所用到的一些常规操作,以下截图都是在notepad++中做的操作:

代码生成

sql生成
提取所有包含某个字符串的行

看到了吧,有没有感觉这些操作很实用,能解决好多重复性工作,而且不用做任何代码开发;正则表达式还有一个常用的操作那就是做字符串型的数据的格式检验,相信大家一定写过一大堆的各种字符串检验,如果使用正则表达式,那这些检验工作会来的更更轻松一些。

结构

正则表达式属于强领域性的工具,其本身基础的理论语言文法太具专业性(主要是不会),本文不做讲解,文末放了一个关于正则基础理论的外部资源,有兴趣的同学可以了解下。这一节主要以功能使用为主线介绍正则表达式的入门技巧,开篇已经说了正则主要功能为:文本检索,文本提取,文本替换,下面先讲下正则表达式的功能符号组成 ,然后主要围绕三点功能来进行讲解。

正则中的各种符号说明

正则表达式如何使用,简单来说就是用正则表达式字符串去操作目标文本,正则表达式所提供的功能都是由字符来提供的, 这和通配符有点像, 但是正则要比通配符强大的多; 正则表达式字符串中比较常用功能字符的有以下几种分类

字符类:主要用来匹配具有宽度的字符和换行符, 字符类也具有定位的功能, 字符类的定位是具有宽度的,在定位功能和定位点不同, 定位点定位是不具有宽度的, 以下是常用的字符类:

\d 用来匹配一个数字0-9

\D 用来匹配一个非数字字符

\w 用来匹配一个非空白非标点符号字符, (我一般很少用这个)

\W 和上面所匹配字符的相反

. 用来匹配任何一个字符,除了换行符(有两个字符:\r \n), 但是多行模式下,.会匹配换行符, 多行模式需要特别指定,对于正则引擎来说,默认的正则匹配模式都是单行, 例如在notepad++,需要在查找界面勾选 查找新行, 在java中需要在正则表达式创建编译时加上参数 Pattern.MULTILINE

任意字符 用来匹配具体的和任意字符相等的字符, 比如:a-z,0-9,汉字,具体的标点符号,空白字符

[任意字符组] 匹配[]组内字符串中的任意一个

[^任意字符组] 匹配不在[^]组内字符串中的任意一个,注意 ^ 这个在[]中的最开头是取反的意思, 匹配非组内字符

\s 匹配任意空白符:空格,换行\r\n,制表符\t

\S 匹配任意非空白符:和上面刚好相反

限定符:用来对字符类进行匹配数量上的修饰

* 匹配0-n个前面所修饰的字符类所能匹配到的字符

? 匹配0-1个前面所修饰的字符类所能匹配到的字符

+ 匹配1-n个前面所修饰的字符类所能匹配到的字符

{number} 这里的number是一个十进制的数字,匹配number个前面所修饰的字符类表达式所能匹配到的表达式

{number,} 这里的number是一个十进制的数字,匹配至少number个前面所修饰的字符类表达式所能匹配到的表达式

{number1,number2} 这里的number是一个十进制的数字,匹配至少number1,至多number2个前面所修饰的字符类表达式所能匹配到的字符表达式

定位点:匹配到某个零宽位置, 就是字符的左边界点或者右边界点, 不会匹配到任何字符

定位点和字符类的区别,字符类也有定位的功能

^ 行的开始

$ 行的结尾,但是这个符号使用的时候和\r\n会冲突, \r\n$和$\r\n不会匹配任何字符, 按照字面的理解 $ 应该定位的是一个点, 这个点应该是在\r\n后面, 那么\r\n$应该是能匹配到\r\n的, 但是在实际的操作中却不是这样, notepad++中没有得到期望的结果.

下面这几个定位符在微软的那里放到了分组里面, 但是提供的功能却仅仅定位, 不过这几个定位符在一些特殊场景下需要多字符定位时显得尤其好用, 开篇的gif动图:保留包含某个字符串的行,中就用到了下面的定位表达式 零宽反向先行预测表达式, 下面的表达式在进行匹配的时候会提前对目标字符串进行扫描匹配到对应的子表达式,然后根据具体的是正向还是负向,选择定位点是在表达式的前面还是后面

(?=子表达式) 定位到表达式能匹配的字符串的左边界点

(?!子表达式) 定位到不在(表达式能匹配的字符串的左边界点)的点, 也就是上面那个表达式不能匹配的到点, 这个表达式都能匹配到

(?<=子表达式) 定位到表达式能匹配的字符串的右边界点

(? 定位到不在(表达式能匹配的字符串的右边界点)的点, 也就是上面那个表达式不能匹配的到点, 这个表达式都能匹配到

分组:用括号将一批字符匹配表达式框住, 可以在匹配表达式后面以反向引用的形式复用表达式\number 等形式, 或者在替换模式下使用\$number等形式

(表达式) 匿名分组, 只用使用\number $number 等以number为形式进行引用

(?<分组名>表达式) 具名分组可以使用\ 、$ 后跟编号或者分组名的形式进行引用

另外分组内的表达式优先级最高,在分组后面的限定符所描述的是分组表达式需要匹配的限定次数,分组在进行引用使用的时候有一点需要注意, 分组的编号是根据其左括号在所有左括号的位置顺序从1进行编码的; 有一个特殊分组就是\0,这个分组匹配到的是整个目标文本


红色括号\1,绿色括号\2,蓝色括号\3

其他常用符

转义符:\ 如果要匹配的字符是正则表达式中的关键字符,则可以用\进行转义, 例如[] 可以转义为[]

引用符:\number \分组名,这个可以在匹配字符进行组表达式复用,例如(hello) world,\1 regular expression, 这个正则能匹配到的串为 hello world,hello regular expression

替换引用符: $number 或者 \分组名 $ 符只能在替换模式下使用, 在notepad++中的替换可以用\number $number进行引用

逻辑操作符:| 或操作符, 优先级最低, | 两边的表达式有一个匹配(|左边的表达式先进行匹配,匹配不成功使用右边的表达式进行匹配), | 操作符两边的表达式的边界可以用分组进行限定.

例如:i can do (every|any)thing for you, 注意这和i can do (every)|(any)thing for you 是不同的,
大家可以拿上面这两个正则表达式来测试下面的文本感受下
i can do everything for you
i can do anything for you

上面介绍了常用的正则表达式中的运算符, 比较完整的运算符介绍可以参考微软的正则表达式, 文末外部资源里面附带了地址.

文本匹配

文本匹配这个功能主要是由字符类和定位符还有限定符组合进行实现的,举几个例子:
匹配大陆的手机号码:+?(86)?1[1-9]\d{9}
邮箱:[a-z]\S*@[a-z0-9]+.[a-z]+
整行都为数字:^\d+$

文本提取

文本提取主要用到是分组,分组可以让你精确取到你想要的文本段,例如一行文本中包含了姓名,出生日期,性别,你想分别提取这几部分信息用作生成sql时,就可以分别对姓名,出生日期,性别进行编组

crow.n,18,male
xiaohong,19,female

查找正则串:^([^,]+),([^,]+),([^\r\n]+)(\r\n)?
替换正则串:insert into students(name,age,sex) values('\1',\2,'\3')\4

上面的例子可以直接在notepad++上测试, 因为文本编辑器里面用到提取的时候也就是在替换模式下进行的, 代码里面可以有api可以调用groups 取分组数组或者map

文本替换

文本替换结合文本提取的功能增强了替换的功能, 这个用处比较多,就像开篇中的gif中展示的功能还有刚才文本提取中的例子, 现在放出另外一个例子,读取csv格式的文件时, 如果需要对将记录行转换为实体,而且字段比较多的话, 这个时候将列头名(如果是英文就更爽了)复制出来,然后将字段使用,或\t替换为\r\n, 最后统一替换为public String \1; 这个时候再根据需要进行类型替换.

一个我常用正则表达式

保留包含字符串的行 (function是要查找的内容,使用的时候替换成你要的字符串就OK了,最后会多出一个空行)
查找:^(?!.*function).*(?:\r\n){0,1}
替换字符串:空字符串

外部资源

正则文法介绍 来自博客园
正则表达式语言 - 快速参考 来自微软的表达式引擎介绍

你可能感兴趣的:(正则表达式)