正则表达式概念详解
正则表达式就是使用一些抽象出来用来代表某类字符的特定字符组成的字符串。
正则表达式是用来在大量字符中匹配(寻找)符合自身字符规则的字符串。
正则表达式是一种规则(人为定义的用某些字符表示一类字符的规则)。
下面主要说明定义正则表达式规则所抽象出来的所有字符所包含的意义。
1. 元字符
. 匹配除了换行符以外的任意字符
.... --> asdf
\w 匹配字母、数字、下划线、汉字
\w\w\w\w --> a3_我
\s 匹配任意空白符(空格,换行,制表符)
\d 匹配所有数字
\d\d\d\d --> 1234
\b 匹配单词的开始或结束
\bhi\b 在文本asdfawef hi asdfwz中会匹配hi,在文本dsfgsdfgsdfghidsfgsdfgsd不会匹配其中的hi单词,即\b要匹配一个单词的起始位置,起始位置必须是各种空白符,但是\b单独不匹配空白符,有单词才匹配空白符。如果使用\b\b测试,不会匹配任何字符。
^ 匹配字符串的开始
^用来查看字符串的开始位置是否有符合目标的,^hi 在文本hisdafsdfawsef中可以匹配hi,但是在文本sadfasdfhiasdfsad、 hiasdfasdfasdf(第一个是空格)中都不会匹配任何字符,如果是在多行模式下,换行符相当于字符串的结束位置。
$ 匹配字符串的结束
$用来查看字符串的末尾是否有符合标准的, $hi 在文本asdfasefashi中匹配hi,但在文本asdfawefasdhiasdfas、fasdfasdffasdahi (最后一个是空格)不会匹配任何字符,如果是在多行模式下,换行符相当于字符串的结束位置。
2. 字符转义
正则表达式规则定义了一些具有意义的字符,如果想使用正则表达式匹配这些特定字符就需要使用转义的方式,就是在 这些字符的前面加上一个反斜杠。
\* 匹配 *, \. 匹配 ., 如果要匹配\,也要使用转义 \\ 。
3. 重复
* 重复0次或多次
.* 代表任意字符重复0次或者多次,可以匹配 dsfasdfadasd、fase、(什么也没有)。
+ 重复1次或多次
.+ 代表任意字符重复1次或者多次,可以匹配 dsfasdfadasd、fase。
? 重复0次或1次
.? 代表任意字符重复0次或者1次,可以匹配 a、1、_、(什么也没有)。
{n} 重复n次
.{5} 代表任意字符重复5次,可以匹配 asdfa、s des、122 4、 (五个空格)。
{n,} 重复n次或n次以上,注意括号中逗号后面是没有空格的
.{5,} 代表任意字符重复5次或者5次以上,可以匹配 fassd、fsdafsdfasdf、fasdfasdf sdf2we 。
{n,m} 重复n到m次。
.{5,10} 代表任意字符重复5到10次,包含10次,可以匹配 dasfasdf、sddwe、xzczcwesdv。
4. 字符集
使用中括号 [] 把一些字符括起来组成一个字符集。
[aeiou] 匹配 sdfwaefdaxdfawefiousdfiuo。
[+*-?!$^.] 这些符号都可以匹配到并且不用转义, 在字符集中只有 \ 需要使用转义,其他字符都不需要。 fa.sdfas+-asdf*asdfgsa$sd^asdfgs?sdgfa
[1-9] - 号还可以当做表示一个范围的符号(只有在字符集中且前面的字符编码比后面的字符编码小才可以,前大后小会出错)。 23678532813zxd23wedfas 不匹配0
[\\] 转义之后才可以匹配 \ asdefasdasfedf\asdfaw\asdfx\sd
由以上的例子可以看出,字符集就是用来查找某一个位置的字符是否符合字符集中的某个字符。
注: 字符集中 ^ 这个符号在第一位和其他位置的意义不同,在其他位置才代表匹配^号,在第一位的情况会在 第6 节反义 里面说明。
5. 分支
使用 | 符号可以实现 或 的意义。
\d{5}-\d{4}|\d{5} 匹配 5位数字-4位数字 或者 5位数字 --> 11111-1111 或者 11111
\d{5}|\d{5}-\d{4} 匹配 5位数字 或者 5位数字-4位数字 --> 11111 或者 11111-1111
但是要注意的是,第二个表达式不会匹配到或后面的形式,因为正则表达式的或语句在查找的时候是从左到右进行对比的,如果前面的匹配就不会在查看后面的了。也就是说,使用第二个表达式,如果有11111-1111的形式,由于前面5个1已经符合了或前面的形式,故只会查找出来前五位组成11111。劳务派遣
6. 反义
\W 匹配除字母、数字、下划线、汉字以外的字符
\S 匹配除了空白符意外的字符
\D 匹配除了数字意外的字符
\B 匹配不是单词开头和结束的位置
以上4个使用符号没什么大的变化就不举例说明了。
[^x] 匹配除了x之外的任意字符
[^wasd] 匹配除了wasd之外的任意字符
使用字符集定义反义的这种方式一定要注意的是 ^这个符号必须在字符集的第一位,且该符号后面有一个任意符号才可以生效,匹配除了^后面所有的符号之外的符号。
例如:
[^asdfawef++!!@_] 这种就是除了asdfawef++!!@_之外的任意符号
[sdfasdf^awef] 而这种只是一个字符集而已
7. 分组
通过 第三节重复 我们已经掌握了对单个字符重复的方法,但是如何对多个字符进行重复呢?
使用 () 小括号将需要整体重复的部分括起来之后使用 之前说的重复方法进行重复的设置即可。
(\d{5}-\d{4}|\d{5}){2} 这个式子将 11111-1111或者11111 这种形式重复了两次 12345-678912345-678912312,1231234121234。
每次使用一对 () 小括号,就是分了一个组,这个组的内容就是括号里面的正则表达式,并且要注意的是每个组都有一个组号(编号),这个组号是自动分配的,分配原则是:
1. 从左到右分配组号,第一个组是1,依次类推。(正则表达式整体是一个组,组号是0)
2. 实际上会从左到右查找两次,第一次给未命名的组分配组号,第二次给已命名的组分配组号。
3. 可以使用(?:xxx)的语法来让一个组不参与自动分配组号。
下面的后向引用、零宽断言、负向零宽断言、注释都是对 () 的使用技巧。也就是分组的使用技巧。
8. 后向引用
后向引用是指通过 反斜杠\ 加上 数字(组号)的方式来重复使用某一组的正则表达式。
例如: (\d+)\s{1}\1 这个式子中可看出 \d+ 是第1组,组号就是1,后面的\1就是引用了前面这一组的内容,相当于 (\d+)\s{1}(\d+)。用于匹配一些数字中
间有一个空白符之后又是一些数字的形式。
\b(\w+)\b\s+\1\b 同样这个式子中 \w+ 是第一组,组号是1,后面使用了\1的方式引用了前面的内容。用于匹配 go go 、hello hello 这种形式。
还有一种情况是某一组如果通过(?<name>exp)这样的语法设置了一个名字,可以通过上面说的方法引用,还可以使用 \k<name> 这样的方法引用该表达式。例如:\b(\w+)\b\s+\1\b 也可以写成 \b(?<Word>\w+)\b\s+\k<Word>\b
最后,我们还可以使用(?:exp)这样的语法使一个组得不到组号。
注: 要使用 后向引用 一定要对要引用的那个组的组号很清楚。
9. 零宽断言
零宽断言有两种:
1. 零宽度正预测先行断言 (?=exp)
这个语法能断言自身出现的位置的后面能匹配到exp表达式,最后输出结果不包括exp匹配的字符
例如: \b\w+(?=ing\b) 这个式子用来匹配 以ing结尾的单词,但不包含ing dsfasfaasd wsding sadfa aoweing asdaing
2. 零宽度正回顾后发断言 (?<=exp)
这个语法能断言自身出现的位置的前面能匹配到exp表达式,同样最后输出的结果不包含exp匹配的字符
例如: (?<=\bre)\w+\b 这个式子用来匹配 以 re 开头的单词,但不包含re sfafalinn resadfasil klkjresafdssj
10. 负向零宽断言
负向零宽断言也有两种:
1. 零宽度负预测先行断言 (?!exp)
这个语法能断言自身出现的位置后面不能匹配exp表达式
例如:\d{3}(?!\d) 匹配三位数字,并且这三位数字后面不能是数字 hkhkh123hkkbjkb4353jkhh213
2. 零宽度负回顾后发断言 (?<!exp)
这个语法能断言自身出现的位置前面不能匹配exp表达式 例如:(?<![a-z])\d{7} 匹配前面不是小写字母的七位数字 asdkfhlkh123123412hkhASEDAK131241231
举例:(?<=<(\w+)>).*(?=<\/\1>) 能匹配两个标签之间的内容 <b>asdfaweasdfasdfs</b>
11. 注释
使用(?#comment)这种语法可以给表达式添加注释,是阅读变得容易一点。
例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)
还有一种使用注释的方法,就是启用“忽略空白”模式,在此模式下所有空白被忽略,并且启动使用#的注释方法。此模式下#后面的到这一行结束的所有文本都会被当做注释:
(?<= # 断言要匹配的文本的前缀 <(\w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签) ) # 前缀结束 .* # 匹配任意文本 (?= # 断言要匹配的文本的后缀 <\/\1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签 ) # 后缀结束
12. 贪婪与懒惰
在匹配时你会发现如果不加以限制,正则表达式会去匹配符合当前要求的最长的字符串,例如a.*b这样的表达式,在匹配aaabab时会匹配整个字符串(aaabab),这样的匹配方式成为贪婪匹配;还有一种匹配方式,就是在符合要求的前提下尽可能短的匹配,只要给表达式合适的位置加一个?就行,这种匹配方式称为懒惰匹配。例如使用懒惰匹配去匹配aaabab时会得到aaab、ab两个子串。
参照表中的写法即可。·
13. 处理选项
正则表达式有以下几种不同的模式。
14. 平衡组/递归匹配
如何匹配<ASdfas<Asdfasdf<asdfa<adga>>>>这样多个括号嵌套的字符串?
正则表达式提供三种语法组合使用来匹配这样的字符串。
(?'group') 把捕获的内容命名为group,并压入堆栈
(?'-group') 弹栈操作,弹出命名为group的捕获内容
(?(group)yes|no) 判断堆栈,如果有group执行yes,没有匹配no
举例说明:要匹配 <ASdfas<Asdfasdf<asdfa<adga>>>>>>>>
使用的表达式为(((?'open'<)[^<>]*)+((?'-open'>)[^<>]*)+)*(?(open)(?!))
注: 这个表达式最后一个组里使用的(?!)是零宽度负预测先行断言,由于后面没有表达式,所以匹配一定会失败,即当group还有,也就是匹配yes的时候就匹配失败。
15. 其他