正则表达式是强大,便捷,高效的文本处理工具。正则表达式本身,加上如同一门袖珍编程语言的通用模式
表示法,赋予使用者描述和分析文本的能力。配合上特定工具提供的额外支持,正则表达式能够添加,删除,
分离,叠加,插入和修整各种类型的文本和数据。
完整的正则表达式由两种字符构成。特殊字符称为”元字符“,其他为普通文本字符。
1. 行的起始与结束
^
用于将匹配文本锚定在一行的开头
$
用与将匹配文本锚定在一行的结尾
^cat 匹配以c作为一行的第一个字符,紧接着一个a, 紧接着一个t的文本
cat$ 匹配以字符cat为一行结尾的文本
^$ 匹配空行,没有任何字符
2. 字符组与排除字符组
[]
匹配方括号中的若干字符之一
gr[ae]y 匹配字符串gray 或者 grey
H[1-6] 字符组元字符'-'表示一个范围,匹配H1,H2,H3,H4,H5,H6
[0-9A-Z_!.?] 匹配一个数字,大写字母,下划线,惊叹号,点号,或者是问号
[-_.?] 匹配连字符,下划线,点号,问号
注意:
- 字符组以外的普通字符都有“接下来是”的意思,字符组的内容是在同一个位置能够匹配若干字符,它的意思
是“或”。 - 连字符'-'只有在字符组内部并且没有出现在字符组的开头,它才是字符组元字符, 用来表示一个范围,
否则它就只能匹配普通的连字符号。 - 字符. ? 在字符组外是元字符,但在字符组内他们都被当作普通字符。
[^]
匹配一个除了括号中任何未列出的字符
[^1-6] 匹配除了1到6以外的任何字符
q[^u] 匹配q后面紧接着一个除了u以为的任何一个字符
3. 用点号匹配任意字符
.
匹配任意字符
03[-./]19[-./]76 匹配03-19-76, 03.19.76, 03/19/76
03.19.76 匹配03-19-76, 03.19.76, 03/19/76
注意:
- 在字符组中的.并不是元字符,而是普通字符点号
- 在字符组中的-也不是元字符,因为它在字符组的第一个位置
- 在字符组外的.是一个元字符,可以匹配任意字符包括普通字符点号
- 第一个匹配更加精确,但是更难读,也更难写。第二个匹配更容易理解,但是不够细致。使用哪一个正则
表达式,取决于你对检索文本的了解,以及你需要达到的准确程度。写正则表达式时,我们需要在对欲检
索文本的了解程度与检索精确性之间求得平衡。
4. 多选结构
|
匹配分隔两边的任意一个表达式
()
划定多选结构的作用范围
匹配grey 或者 gray
gr[ea]y
grey|gray
gr(a|e)y
匹配Jeffrey 或者Jeffery
Jeffrey|Jeffery
Jeff(rey|ery)
Jeff(re|er)y
匹配以From,Subject或者Date开头紧跟着冒号的字符串
^(From|Subject|Date):
注意:
- 一个字符组只能匹配目标文本中的单个字符,而每个多选结构自身都可能是完整的正则表达式,都可以匹配
任意长度的文本。 - 字符组基本可以算是一门独立的微型语言,对于元字符,它们有自己的规定。而多选结构是正则表达式语言
主体的一部分。
5. 单词分界符
\<
匹配单词的起始位置
\>
匹配单词的结束位置
\<cat\> 匹配单词cat
注意:
- <和>本身并不是元字符,只有当它们与斜线结合起来的时候,整个序列才具有特殊意义,它们被称为
元字符序列。
6. 可选项元素
?
表示在它之前的字符可有可无
colou?r 匹配color 或者 colour
July? 匹配Jul 或者 July
7. 量词
+
在它之前紧邻的元素出现一次或任意多次
*
在它之前紧邻的元素出现任意多次或者不出现
<hr +size=[0-9]+ *> 匹配在size之前至少有一个空格,在=之后至少有一个数字,在>之前有任意多个空格
8. 区间量词
{min, max}
表示在它之前的元素最少出现min次,最多出现max次
[a-zA-Z]{1,5} 匹配1到5个大小写字母
9. 括号及反向引用
()
能够记住它包含的子表达式匹配的文本
\1
引用第一组圆括号匹配的文本
\2
引用第二组圆括号匹配的文本
\<([A-Za-z]+) +\1\> 匹配重复的单词,如 the the
([a-z])([0-9])\1\2 匹配一个字母紧接一个数字,接下来重复之前匹配的字母和匹配的数字 如:a1a1
(?:)
非捕获型括号, 表示只分组不捕获
(?:[a-z])
10. 转义符
在元字符前面使用反斜线称为转义符
\.
转义点号,使它失去元字符的含义,表示一个普通的点号字符
\(
转义圆括号,使它失去分组的作用,作为普通字符的字符
\([a-zA-Z]+\) 匹配在一个括号内的单词如: (very)
11. 环视结构
环视结构不占用字符,只匹配文本中的特定位置,类似与^匹配行的开头位置
(?=)
肯定顺序环视,子表达式能够匹配右侧文本则匹配位置成功
(?!)
否定顺序环视,子表达式不能匹配右侧文本则匹配位置成功
(?<=)
肯定逆序环视,子表达式能够匹配左侧文本则匹配位置成功
(?<!)
否定逆序环视,子表达式不能匹配左侧文本则匹配位置成功
Jeffs 替换为Jeff's
s/\bJeffs\b/Jeff's/g 最简单直接的方法
s/\b(Jeff)(s)\b/$1'$2/g 过于复杂
s/\bJeff(?=s\b)/Jeff'/g 使用了顺序环视,匹配到s左边的位置
s/(?<=\bJeff)(?=s\b)/'/g 同时使用了顺序环视和逆序环视,匹配到'插入的位置
s/(?=s\b)(?<=\bJeff)/'/g 与上面的正则相同,只是颠倒了两个环视结构的顺序匹配结果不受影响
注意:
- \b 在上面的正则表达式中表示单词分界符
- $1 在Perl编程语言中的正则表达式中表示反向引用第一个括号匹配的内容