简书链接:正则匹配高级笔记
文章字数:1239,阅读全文大约需要4分钟

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
限定大小写必须包含 只包含两种
^((?=[A-Za-z])[a-zA-Z]+){3,10}$


(^(?=.*?[A-Z])(?=.*?[0-9])[A-Z0-9]*$)的理解


.*?不能删除,比如这里匹配第二个括号的时候无法匹配整个字符串,但是.*?就ok了,就取出了数字
如果删除第一个里面的.*?呢, AA1是没问题的, 1A就不行了,因为在取出第一个的时候无法和整体进行匹配就得到了空,


改成不带?=呢,那么就多出了自匹配文本 1 2 3了。
(^(?=.*?[A-Z])(?=.*?你)[A-Z0-9]*$)测试 大写和数字,发现无法命中,原因是()里面的都要选中的,然后和后面的组合。所以无法成立了

那么如果不包含?=呢,

代表选择 字母A-Z和 后面的任意匹配
或者选择后面的0-0和后面的任意匹配,但是肯查是代表二选一??

三选一

(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])[A-Za-z0-9]


代表前面的三组任何组合和最后[]中的进行匹配, 那么总共组合有

(?=.*[A-Z]) (?=.*[a-z]) 与后面的[]任意命中,


环视主要有以下4个用法:
(?<=exp) 匹配前面是exp的数据
(?<!exp) 匹配前面不是exp的数据
(?=exp) 匹配后面是exp的数据
(?!exp) 匹配后面不是exp的数据

示例四:
(?<=B)AAA 匹配前面是B的数据,即BAAA匹配,而CAAA不匹配
(?<!B)AAA 匹配前面不是B的数据,即CAAA匹配,而BAAA不匹配
AAA(?=B) 匹配后面是B的数据,即AAAB匹配,而AAAC不匹配
AAA(?!B) 匹配后面不是B的数据,即AAAC能匹配,而AAAB不能匹配

另外,还会看到(?!B)[A-Z]这种写法,其实它是[A-Z]范围里,排除B的意思,前置的(?!B)只是对后面数据的一个限定,从而达到过滤匹配的效果。
^(?=.*?[A-Z])(?=.*?[a-z])[a-zA-Z]*$
这个表达式表示只允许大小写组合,必须大小写组合才能成立

理解1:
[a-zA-Z]* 如果没有 那么写,那么无法通过,为什么呢?
假设输入aB,开始的小写就会被第二个 前瞻(?=)里面的全部匹配上,那么继续往后面走,就会命中[a-zA-Z]里面的A-Z 因为小写已经被吸收了。

假设输入Ba 开始的大写就会被第一个前瞻(?=)里面全部吸收掉,那么走到a的时候也和上面的差不多,是被[a-zA-Z]*匹配上了。
至于最后面填写*为什么也没出错,是因为如果没有匹配那么被前面吸收掉了。


.*? 无法理解,不加上不行。放到()外面的前面就无法过滤其它符号,所以他的含义就是让其它无法通过。
比如Aa可以通过但是aAa就无法通过了,也就是第一个a命中的应该是第二个。

改成 ^(?=[a-z]*[A-Z])(?=[A-Z]*[a-z])[a-zA-Z]*$ 也是可以的。交叉组合,但是.*?给人一种无解,认为可以传递其它,就好比最后面的*$ *完全应该写成+因为*不会成立,只要大写a或者全部小写a就无法通过了。

改造之后变成了

^(?=[a-z]*[A-Z])(?=[A-Z]*[a-z])[a-zA-Z]+$


再解释一次,如果 命中第一个括号,后面的不写aB可以命中的,但是最后面那个不能丢。


aB和 Ba可以直接用
^(?=[a-z]*[A-Z])[a-zA-Z]+$ 但是会导致BBBBB也能直接通过了
用^(?=[A-Z]*[a-z])[a-zA-Z]+$ 也是一样的,能让ABBa 杜能检测,但是纯aa通过了,
所以两个前瞻组合,就能结合为一体,让A a这样纯大写和小写都不能通过。




(^(?=.*[A-Za-z])(?=.*[^A-Za-z0-9])([A-Za-z]
|[^A-Za-z0-9])*$)|(^(?=.*[A-Z])(?=.*[^A-Za-z0-9])(?=.*[0-9])([A-Z0-9]
|[^A-Za-z0-9])*$)
|(^(?=.*[^A-Za-z0-9])(?=.*[a-z])(?=.*[0-9])([a-z0-9]|[^A-Za-z0-9])*$)




Pattern compile = Pattern.compile("(?<=A|B|C|D)Good");//非获取匹配,前瞻 返回的是左边,也就是window 所以后面的.*非贪婪得到了Zbcdefg而不是bcdefg
Matcher matcher = compile.matcher("bbbAGood");


matcher.group()返回的是Good,给?<=再套上1个()group1无法取得数据。




Pattern compile = Pattern.compile("(Window(?=7|8|9|Z)).*");
Matcher matcher = compile.matcher("aWindow78");

group1 =Window也就是被口号包括的
group0 整体 ,返回的是Window78


Pattern compile = Pattern.compile("(Window(?!7|8|9|Z)).*");
Matcher matcher = compile.matcher("aWindow1");
取反,输入Window7将不匹配 输入aWindow1 后group0 =Window group1: Window1



Pattern compile = Pattern.compile("((?<!A|B|C|D))Good");//非获取匹配,前瞻 返回的是左边,也就是window 所以后面的.*非贪婪得到了Zbcdefg而不是bcdefg
Matcher matcher = compile.matcher("bbbGGood");


group0 =Good group1=空,如果输入 bbAGood将无法匹配,这里是后顾取反。





Pattern compile = Pattern.compile("((?<!A|B|C|D))Good");//非获取匹配,前瞻 返回的是左边,也就是window 所以后面的.*非贪婪得到了Zbcdefg而不是bcdefg
Matcher matcher = compile.matcher("bbbGGood");


boolean b = matcher.find();
if (b) {
int i = matcher.groupCount();//group 0返回本身 和其他不同,,这是从1开始才表示原子。
while (i >= 0) {
String group = matcher.group(i);
// String group = matcher.group();
System.out.println("group:"+i+ ":"+ group);
i--;

}
}