正则表达式
正则表达式
@
正则表达式作用及其与字符串匹配的区别
正则表达式一般用来匹配字符串,与字符串匹配算法里面的匹配不太一样,字符串匹配算法是用来匹配一段一模一样的字符串,而正则表达式往往是用来匹配具有某一类规则的字符串。
正则表达式的基本语法
例1:匹配字符串abc
:
正则表达式 | pre |
---|---|
待匹配 | Regular expression |
匹配结果(红色部分) | Regular expression |
例2:匹配coooooooo...k
其中o的个数大于等于零:
正则表达式 | co*k |
---|---|
待匹配 | ck cok cook coook coo |
匹配结果(红色和蓝色部分) | ck cok cook coook co |
以上*
是正则表达式里面的元字符,可以看出,常规的字符串匹配算法无法实现这个需求。
元字符
元字符有:
元字符 | 描述 |
---|---|
. | 句号匹配任意单个字符除了换行符。 |
[ ] | 字符种类。匹配方括号内的任意字符。 |
[^ ] | 否定的字符种类。匹配除了方括号里的任意字符 |
* | 匹配>=0个重复的在*号之前的字符。 |
+ | 匹配>=1个重复的+号前的字符。 |
? | 标记?之前的字符为可选. |
{n,m} | 匹配num个大括号之前的字符或字符集 (n <= num <= m). |
(xyz) | 字符集,匹配与 xyz 完全相等的字符串. |
| | 或运算符,匹配符号前或后的字符. |
\ | 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ | |
^ | 从开始行开始匹配. |
$ | 从末端开始匹配. |
以上为正则表达式自带的元字符,如果需要匹配以上字符,需要在字符前面加上"\"。
点运算符.
点运算符用来匹配除了换行符以外所有的字符。
例3:
正则表达式 | a..b |
---|---|
待匹配 | accb acb aabb ab |
匹配结果(红色部分) | accb acb aabb ab |
以上,a..b
有两个点,意思就是要匹配a和b之间有两个出换行符外任意字符的字符串。
字符集[]
字符集里面所有的字符都会被匹配到,不论顺序,不论多少,任何一个字符都是单独的存在,比如要匹配 Regular expression
中所有的元音字母。
例4:
正则表达式 | [aeiou] |
---|---|
待匹配 | Regular expression |
匹配结果(红色部分) | Regular express<ion |
否定字符集[^]
否定字符集,字面意思,匹配与上面字符集相反,比如要匹配 Regular expression
中所有的辅音字母。。
例5:
正则表达式 | [^aeiou] |
---|---|
待匹配 | Regular expression |
匹配结果(红色部分) | Regular expression |
重复*
+
?
重复某一种模式匹配的次数,后面跟着*
,+
,?
它们在别的情况下可能有别的用法
元字符 | 重复次数 |
---|---|
* | >=0次 |
+ | >=1次 |
? | 等于0或等于1次 |
这个重复是重复字符前面的内容。
例6:
正则表达式 | co*k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
例7:
正则表达式 | co+k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
例8:
正则表达式 | co?k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
{ }
号
在正则里面它表示一种量词,也算是重复,跟上面的重复相比,它更加的精确。比如看一串数字是不是QQ号,QQ号位数为5-11位,就可以这样写[0-9]{5,11}
。
如果大括号里面没有,
就是表示匹配几次,例如cook
和co{2}k
是一样的意思。
如果大括号里面有,
但是没有第二个数字,就是要匹配至少第一个数字的重复,上不封顶。
例9:
正则表达式 | co{3}k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
例10:
正则表达式 | co{2,}k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
例11:
正则表达式 | co{1,3}k |
---|---|
待匹配 | ck cok cook coook |
匹配结果(红色部分) | ck cok cook coook |
特征标群( )
前面提到的所有重复,都是指重复前面的一个字符,但是要重复一个字符串怎么办呢,这里就能用到特征标群,在( )
里面的字符串对外当一个字符处理,不单单如此,特征标群里面也可以是一个表达式。
例12:
正则表达式 | (ab)+c |
---|---|
待匹配 | abc ababc abababc ac |
匹配结果(红色部分) | abc ababc abababc ac |
例13:
正则表达式 | (a|b|c)d |
---|---|
待匹配 | ad bd cd abcd |
匹配结果(红色部分) | ad bd cd abcd |
转义符\
如果要匹配一些有特殊意义的字符本身就需要在其前面加上转义符\
,例如要匹配.
,就要写成\.
。
锚点^
$
^
号用来判断字符串是否在匹配字符串的开头。
$
号用来判断字符串是否在匹配字符串的结尾。
例如要判断一个字符串是否以"c"开头以"k"结尾。
例14:
正则表达式 | (^c).*(k$) |
---|---|
待匹配 | coo cook ook |
匹配结果(红色部分) | coo cook ook |
简写字符集
有时我们要匹配数字,就会用到[0-9]
这样的的正则表达式,而这种匹配又太过于常用,于是就有了简写字符集来减小代码量,比如匹配数字可以用\d
来代替,就会使代码显得很精简。
简写 | 描述 |
---|---|
. | 除换行符外的所有字符 |
\w | 匹配所有字母数字,等同于 [a-zA-Z0-9_] |
\W | 匹配所有非字母数字,即符号,等同于: [^\w] |
\d | 匹配数字: [0-9] |
\D | 匹配非数字: [^\d] |
\s | 匹配所有空格字符,等同于: [\t\n\f\r\p{Z}] |
\S | 匹配所有非空格字符: [^\s] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
\p | 匹配 CR/LF(等同于 \r\n ),用来匹配 DOS 行终止符 |
零宽度断言
它不作为是匹配的一部分,它只是一种约束,比如说我要匹配大于等于1个o
,一般正则表达式应该这样写o+
,但是我又一个条件,我要求这些o
前面要有一个c
,后面有一个k
,但是这两个字母又不在我的匹配要求字符串里面,所以这里就用到了零宽度断言。
符号 | 描述 |
---|---|
?= | 正先行断言-存在 |
?! | 负先行断言-排除 |
?<= | 正后发断言-存在 |
?<! | 负后发断言-排除 |
?=
正先行断言
?=一个正则表达式
,就是表示,也是约束待匹配的字符串后面必须跟着满足那个正则表达式的字符串。
比如要匹配大于等于o
,但是要求后面跟着一个k
例15:
正则表达式 | o+(?=k) |
---|---|
待匹配 | oook ook ok o |
匹配结果(红色部分) | oook ook ok o |
?!
负先行断言
?!一个正则表达式
,就是表示,也是约束待匹配的字符串后面必须不能跟着满足那个正则表达式的字符串。(与正先行断言相反)
比如要匹配大于等于o
,但是要求后面不能跟着k
例16:
正则表达式 | (?<=c)o+ |
---|---|
待匹配 | oook ook ok o |
匹配结果(红色部分) | oook ook ok o |
?<=
正后发断言
跟正先行断言类似,不过前者是约束以特定字符串结尾,这个是约束以特定字符串开头。
例如查找以c
开头的大于等于一个的连续的o
例17:
正则表达式 | (?<=c)o+ |
---|---|
待匹配 | cooo coo co o |
匹配结果(红色部分) | cooo coo co o |
?<!
负后发断言
与正后发断言相反,它是排除。
例如查找不以c
开头的大于等于一个的连续的o
正则表达式 | (?<!c)o+ |
---|---|
待匹配 | cooo coo co o |
匹配结果(红色部分) | cooo coo co o |
标志
标志也叫模式修正符,因为它可以用来修改表达式的搜索结果。这些标志可以任意的组合使用,它也是整个正则表达式的一部分。
标志 | 描述 |
---|---|
i | 忽略大小写。 |
g | 全局搜索。 |
m | 多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。 |
这些标志的使用方式为/正则表达式/标志
例如查找所有字母就可以这样写/[a-z]/gi
为什么是gi
因为如果不用g就只会匹配出现的第一个英文字母,要加上全局搜索g才能全部匹配出来,前面的所有例子都是用了全局搜索的。
m就相当于是把一个字符串里面的换行都变成结束标记,但是又不分割该字符串(让^
和$
每行都能生效),例如要匹配a
后面接上一个除了换行符以外的字符。
正则表达式 :/a(.)?$/
待匹配: a
a
a
a
这样只能匹配到最后一个a,因为只有最后一个a不是以换行结尾。
正则表达式 :/a(.)?$/gm
待匹配: a
a
a
a
这样所有的a都能匹配上,因为修饰符m相当于是吧所有的换行都自动替换了,所以都能匹配上。
贪婪匹配与惰性匹配
正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ?
将贪婪匹配模式转化为惰性匹配模式。
例如我要匹配出一个字符串内所有以c开头以k结尾的子串。
正则表达式 | /(?<=c).*(?=k)/ |
---|---|
待匹配 | ckcokcook |
匹配结果(红色部分) | ckcokcook |
明显不满足,这体现了正则表达式的贪婪模式
转化为惰性模式
正则表达式 | /(?<=c).*?(?=k)/ |
---|---|
待匹配 | ckcokcook |
匹配结果(红色部分) | ckcokcook |
本文部分参考:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md