RE正则

RE(regular expression)称为正则表达式。实现对字符串的匹配。至于说匹配到了之后要做啥,那就取决于具体情况了,RE所做的只是提供一套规则,实现对字符的匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
类似于占位的符号	-->元字符
. #匹配单个字符,不匹配\n(换行)。 1

以下都是对前一位进行的匹配 -->量词,重复次数
? #前一项出现一次或者不出现 0/1
eg: abc? 匹配ab或abc
+ #前一项出现一次或者以上 [1,+∞)
* #前一项出现0次或者0次以上 [0,+∞)
eg: .* 可以匹配任意字符任意次数,不包含换行符号
{m,n} #前一项出现的次数范围 [m,n]
{m,} [m,+∞)
{m} m次

分组 -->前面说的都是针对单个字符,括号可以作用于字符串
() #对模式进行分组。
eg: (hello)? 可以匹配 hello 或者 hellohello
分组的命名
(?<groupname>expression) #expression为表达式,groupname为组的命名
eg: (?<a1>[^=]+)
匹配expression,但是不捕获匹配文本,也不给分组编号。可以方便的去除不需要的分组信息
(?:expression)

选择
| # (a|b)
eg: 0\d{2}-\d{8}|0\d{3}-\d{7} #匹配011-12345678或者0718-1234567这样的电话号码

指定字符
[abcdefg] #匹配其中任意一个字符
[^abcdefg] #匹配非其中任意一个字符,不需要使用|

范围字符
-
eg: [a-zA-Z] #匹配任意一个字母
[0-9] #匹配任意一个数字

取反
^
[^a-z] #取非小写字母

以下也有类似占位的作用
简写
\n #空格
\t #table
\r #换行
\f #form-feed

\d #数字
\D #非数字
\w #单词(字母、数字、下划线、汉字)
\W #非单词
\s #空白,等于 [\n\t\r\f]
\S #非空白
eg: [\d\D] 可以指任意字符,包括换行符号

锚定archor
行锚定:
^ #开头
$ #结尾
词锚定:
\bword\b #匹配完整单词
\bword #匹配单词开头
word\b #匹配单词结尾
\bword\B #匹配非word
\B #非界词锚定

非贪婪数量词
? #尽可能少的匹配。找到第一个满足的匹配就停止匹配,让匹配速度变快
eg: abcdbeb
abc.*?b #只会匹配abcdb

零宽断言
刚好今天写的oracle语句中regexp_substr中需要这个东西,没办法,不知道这个用法,弄了好久没写出来,因为我需要的是某个字段,但是用于匹配的这个字符串又不是我需要的。最后还是将查询出来的结果作为一个新的表,再在字段上进行分隔。
eg: 例如从某字段adgsaf sdfasd source=somewordneed jkjl dest_name=somewordfind alkslkk23kjl中找出somewordneed和somewordfind

select f1,f2,regexp_substr(source,'[^=]+',1,2),regexp_substr(dest,'[^=]+',1,2)
from (
select t.name f1,p.name f2,
regexp_substr(p.args,'source=\S*',1,1) source,regexp_substr(p.args,'dest_name=\S*',1,1) dest
from sometable1 t left join sometable2 p
on t.m=p.m and t.o=p.o
where t.m=(select m from sometable1 where name like 'someword' and o is null)
and t.o is not null and p.s='1'
order by t.name,p.name
desc
);

零宽断言的作用在于我在匹配字符串的时候需要用到某些字符作为标志,但是我需要的部分呢,又不包含这个标志,而是这个标志匹配到的其它部分。
1.正预测先行断言,后面为匹配表达式部分
?=expression
eg: i have a dream
\b\w+(?=ve\b) #匹配ha,后面的ve不显示
2.正回顾后发断言,前面为匹配表达式部分
?<=expression
eg: 前面的oracle中匹配部分可这样写
regexp_substr(p.args,'\b(?<=source=)\w+\b',1,1) source #这样就可以直接取出source=后面的部分,而source=不会被取出来。
不过oracle并不支持这个语法。

3.负向零宽断言,即正向零宽断言的否定
?!expression
\b\w+q(?!u)\w+\b #匹配q后面有字母,但是字母不是u的词
?<!expression
\b\w(?<!q)u\w+\b #匹配u前面有字母,但是字母不是q的词

后向引用
简单说就是再次引用前面分组的内容
如果没有命名分组,那么就只能用数字引用
\b(\w+)(\d+)(\1)(\2)\b
等于\b(\w+)(\d+)(\w+)(\d+)\b

有命名的分组使用分组名
\b(?<name>\w+)(\k<name>)\b