第一次接触正则表达式的时候一脸懵逼,相信很多人都和我一样的感受。万幸最近找到一篇文章,学到很多,因此记录一下。
概念
正则表达式描述了一种字符串的匹配模式,可以用来检查一个串是否含有某种子串,将匹配的字串做替换或者取出符合匹配条件的字串。
它是由普通字符(a-z 、A-Z 、 0-9 等)以及特殊字符组成的规则,它作为一个模板,将其他字符串与之进行匹配,得到匹配结果(true/false)。
特点
正则表达式是简单的,同时又是复杂,特性:简单而又功能强大,因而就决定了它的复杂。
普通字符
首先来认识一下普通字符,字母、数字、汉字、下划线以及没有特殊含义(后面会有解释)的标点符号都是普通字符,在用正则匹配时,匹配的就是字符本身。
举例:
表达式 | 匹配 |
---|---|
"c" | 在匹配字符串"abcdefg"时,匹配到字符"c",匹配成功 |
"abc" | 在匹配字符串"abcdefg"时,匹配到字符"abc",匹配成功 |
"我" | 在匹配字符串"我爱学习"时,匹配到字符"我",匹配成功 |
转义字符
不是原来的字面意思,转为其他含义。
如:
表达式 | 说明 |
---|---|
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\s | 匹配一个任意空字符 |
\S | 匹配一个任意非空字符 |
还有一些下面的特殊字符,在前面加"",表示匹配字符本身。
特殊字符
所谓特殊字符,就是有特殊含义的字符,在正则中含义是固定的。
表达式 | 说明 |
---|---|
^ | 这个符号有两种意思,下面会有具体解释 |
$ | 匹配的字符的位置在末尾 |
. | 可以匹配除换行符以外的任意字符 |
还有其他特殊字符,下面会分类进行解释和如何使用。对于这些特殊字符,在字符前加"",在匹配时匹配的是字符本身,如:"^"、 "$"、 "." 其实匹配的是"^"、 "$"、 "."。
表达式
1、匹配多个字符
字符的一对一匹配很好解释和理解,但是还有一些其他的书写方式,用于一对多的匹配,即一个字符匹配多个字符中的任意一个,就表示匹配成功。虽然可以匹配其中多个字符,但是只能是一个字符。
表达式 | 说明 |
---|---|
\d | 0-9任意一个数字,只能是一个 |
\w | 字母A-Z a-z 数字0-9 下划线_ 中的任意一个,只能是一个 |
\s | 任意一个空字符 |
表达式的理解比较抽象,我们举例说明:
表达式 "\d\d" 在匹配 "123" 时,匹配成功,匹配到的内容是"12"。因为"\d"表示任意一个0-9的数字,所以两个"\d"就表示匹配两个连续的数字,即“12”。
表达式 "a.\w" 在匹配 "55a5b556"时,匹配成功,匹配的内容是"a5b"。表达式的意思是连续三个字符,第一个是"a",第2个是任意非换行符的字符,第3个是字母或数字或下划线,即"a5b"。当然,如果字符中有"acc"、"a55"、"a.5"也表示匹配成功。
2、匹配自定义的多个字符
要匹配自定义的多个字符就要用到集合符合[ ],可以将要匹配的多个字符放在里面,如:[abc345]。
如果在集合的字符之前加"",如[abc345],就表示匹配除了a、b、c、3、4、5以外其他任意一个字符。
表达式 | 说明 |
---|---|
[a1b2c3] | 可以匹配a、b、c、1、2、3中的任意一个 |
[^a1b2c3] | 可以匹配a、b、c、1、2、3以外的任意一个字符 |
[a-f5-9] | 可以匹配a-f之间和5-9之间的任意一个字符 |
[^a-f5-9] | 可以匹配a-f以外或5-9以外的任意一个字符 |
举例:
表达式"[mq][abc][123]" 在匹配"mb3k56a"时,匹配成功,匹配到的内容是"mb3"。
表达式"[^mq][abc]"在匹配"mb3k56a"时,匹配成功,匹配到的内容是"6a"。表达式的意思是匹配两个字符,第一个不是m 不是q,第2个字符是a b c 三个字符中的一个。
3、匹配次数设置
匹配次数就是重复匹配的次数。有些字符比较长,对于相同规则的可以进行简化。比如上面提到的"\d\d"就可以简化成"\d{2}",即两个连续的数字,因为第一个是数字,匹配两次,即匹配两个字符,第2个也是数字。
表达式 | 说明 |
---|---|
{n} | 匹配固定次数 |
{m,n} | 至少匹配m次,最多匹配n次,(m<n) |
{m,} | 至少匹配m次 |
* | 匹配任意次 |
? | 匹配0次或匹配1次 |
+ | 至少匹配1次 |
举例:
表达式"\d{11}" 可以匹配连续的11个数字,{11}表示匹配11次,即11个字符
表达式"\d+.\d" 在匹配"it is ¥12.5"时,匹配成功,匹配到的内容"12.5",表达式的含义:小数点前至少有一个数字,小数点后有一个数字
表达式"go{2,8}gle" 可以匹配"goooooogle",{2,8}表示至少匹配两次,最多匹配8次,所以6个"o"能匹配上。
4、其他意义抽象的特殊符号
表达式 | 含义 |
---|---|
"^" | 与字符串开始的地方进行匹配,但不代表任何字符,也不匹配任何字符 |
"$" | 与字符串结束的地方匹配,但不代表任何字符,也不匹配任何字符 |
"\b" | 匹配一个字符串的边界,也就是一个位置,左右两边一边是字符,一边不是字符,是一个单词的边界,本身不代表任何字符,也不匹配任何字符 |
还是举例说明:
a、表达式"^aaa" 在匹配"aaabbccc"是匹配成功,因为"^"要求三个连续的"a"必须在字符串的开始的位置,在匹配"xxxaaaxxx"时,匹配失败,因为"aaa"不在字符串开始的位置。
b、表达式"$bbb"在匹配"aaaccbbb"时匹配成功,因为"$"要求三个连续的"b"必须在字符串结束的位置,在匹配"xxxbbbxxxx"时,匹配失败,因为"bbb"不在字符串结束的位置。
c、表达式".\b."在匹配"@@@abc"时匹配结果:"@a",因为"."表示任意非换行符的字符,"\b"是一个限制条件,要求左右两边一边是字符,一边不是字符,所以就匹配到"@a"。
d、进一步说明,"\b"和"^"、"$"本质是一样的,符号本身不匹配任何字符,都是限制条件。
举例"\bend\b"在匹配"weekend,endfor,end"时,匹配成功,因为表达式中的"e"和"d"都是字符,而"\b"要求匹配的位置一边是字符,一边不是,所以"e"左边必须不是字符,"d"右边必须不是字符,所以匹配到最后的"end",因为之后最后的"end"左右两侧才不是字符,而是字符的边界。
5、表达式优先级设置
表达式 | 含义 |
---|---|
"|" | 或的意思,两者符合一个就行 |
"()" | 一组括号,两层含义:①、在被修饰匹配次数的时候,括号中的表达式可以作为一个整体被修饰;②、取匹配结果的时候,括号中的表达式匹配的内容可以作为一个整体被单独得到 |
举例:
表达式"Tom|Jack"在匹配字符串是时"I'm Tom,he is Jack" 匹配到的数据是"Tom",匹配下一个时匹配的是"Jack"。
表达式"(go\s)+"在匹配"Let's go go go!"时,匹配到的内容是"go go go","\s"表示任意一个空白字符," * "表示任意次数,所以"( )"匹配到的内容是"go "[ go后面是有空格的 ],"+"表示最少出现一次,所以可以匹配多次"go ",所以匹配到到"go go go"
表达式"¥(\d+.\d)"在匹配"$12.9,¥20.5"时,匹配成功,匹配到"¥20.5"。
6、反向引用\1、\2......
表达式在匹配时,经常使用"( )"将其作为一个整体进行匹配,同时又将匹配到的结果保存下来。而在实际应用开发中,在匹配到结果之后,我们在后边的表达式中还想用,简单的方法是将其重新写一下,但是如果是复杂的,再重新写就比较麻烦,而且如果多次使用的话就更麻烦,针对这个问题,正则给了一个简单的使用方法:反向引用。
引用方法是""再加上数字序号,数字序号的意思是表示引用第几个括号,如"\1"引用第一个括号匹配的值,"\20"引用第20个括号匹配的值........以此类推,如果一个括号内包含另一对括号,则从外向内、从做向右编号。
举例:
表达式"('|")(.?)(\1)"在匹配" 'Hello',"world" "时匹配到" 'Hellow' ",下次匹配时匹配到" "World" ",其中"(\1)"表示"('|")"匹配到的内容。
表达式"(\w)\1{4,}"在匹配"aa bbbb ccccc 111121111 999999999"时匹配到"ccccc",再次匹配时匹配到"999999999","(\w)"最少出现5次。
表达式"<(\w+)\s(\w+(=('|").?\s)>.?</\1>)"在匹配" <td id='td' style="bgcolor.white"></td>"匹配成功,如果<td></td>不配对,则匹配失败。
上图:
图中的序号就是在引用时的顺序,方便大家理解。
7、正则表达式的高级规则(贪婪模式和非贪婪模式)
贪婪模式:
在使用次数修饰符修饰表达式的时候,有几种表示方法可以使同一个表达式能够匹配多次,比如"{m}"、"{m,n}"、"?"、" * ",这种重复的匹配次数的表达式在匹配过程中,总是尽可能的多匹配,这种模式就是贪婪模式。
举例:针对字符串"dxxxdxxxd"
表达式 | 解释 |
---|---|
(d)(\w+) | "(\w+)"将匹配字符"d"之后的所有字符,即"xxxdxxxd" |
(d)(\w+)(d) | "(\w+)"将匹配第一个"d"和最后一个"d"之间的所有字符,即"xxxdxxx",虽然"(\w+)"也能匹配上最后一个"d",但如果匹配了最后一个"d",则表达式就不能匹配成功,所以"(\w+)"会让出最后的一个"d",从而促使表达式匹配成功 |
由此可见,"\w+"在匹配的时候总是尽可能多的匹配符合它规则的字符,虽然第2个举例中它没有匹配最后的一个"d",但那是为了让整个表达式能够匹配成功;同理,在使用" * "、"{m,n}"时都是尽可能多的去匹配,在使用"?"进行可有可无的匹配时也是尽可能要匹配,这就是贪婪模式。
非贪婪模式:(容易满足)
在修饰匹配次数的符号后加上符号"?",则可以使匹配次数不定的表达式尽可能少的匹配,只要满足规则就行,不需要对整个字符串匹配,在可有可无的进行匹配时选择不匹配,这种匹配模式称为“非贪婪模式”,当然如果在匹配中少匹配会导致匹配失败的话,还是会进行贪婪模式的多匹配,以使表达式匹配成功。
非贪婪模式的匹配原则:如果少匹配能是表达式匹配成功,则少匹配;如果少匹配时匹配失败,则进行多匹配,保证匹配成功。
举例:针对字符串"dxxxdxxxd"
表达式 | 解释 |
---|---|
(d)(\w+?) | 根据非贪婪模式的原则,"\w+?"尽可能少的匹配,所以只能匹配到一个字符,即字符"d"后面的"x" |
(d)(\w+?)(d) | 根据非贪婪模式的原则,尽可能少的匹配,所以"\w+?"能匹配到第一个"d"和第二个"d"之间的字符"xxx",如果第二个"d"改成其他字符,则匹配到的是第一个和最后一个之间的所有字符 |
外篇:(一起共同学习进步)
QQ群:541144061
网友评论