正则表示式简介
正则表示式基本上包括两种字符:字面意义字符与元字符。
字面意义字符是指按照字面意义比较的字符;
元字符是不按照字面比较,在不同情境有不同意义的字符。
1. 字面意义字符
字符 | 说明 |
---|---|
字母或数字 | 比较字母或数字 |
\\ | 比较\ |
\0n | 八进制0n字符(0<=n<=7) |
\0nn | 八进制0nn字符(0<=n<=7) |
\0mnn | 八进制0mnn字符(0<=m<=3,0<=n<=7) |
\xhh | 十六进制0xhh字符 |
\uhhhh | 十六进制0xhhh字符 |
\xh…h | 十六进制0xh…h字符 |
\t | Tab(\u0009) |
\n | 换行(\u000A) |
\r | 返回(\u000D) |
\f | 换页(\u000C) |
\a | 响铃(\u0007) |
\e | Esc(\u000B) |
\cx | 控制字符x |
元字符在正则表示式中具有特殊的意义,如! $ * ( ) + = { } [ ] | \ : . ?等。若要比较这些字符,则必须加上忽略符号\。如果不确定哪些标点符号字符要加忽略符号,可以在每个标点符号前加上\。
使用java字符串撰写正则表示式比较麻烦。
将正则表示式\|放入” “之间时,按照java字符串规定必须忽略\|中的,所以必须写成”\\|”
for(String token : "Justin|Monica|Irene".split("\\|")){
System.out.println(token);
}
注意:在Java中使用字符串撰写正则表达式时,先写下正则表达式,再在每个\前加上\。
2. 字符类
正则表示式中,多个字符可以分归在一起,成为一个字符类。
一个字符类定义一组字符,其中的任一字符均可出现在输入字符串中以便成功匹配。
归类字符的方式之一是将字符放于[ ]中。
字符类 | 说明 |
---|---|
[abc] | a或b或c任一字符 |
[^abc] | a、b、c以外的任一字符 |
[a-zA-Z] | a~z或A~Z任一字符 |
[a-d[m-p]] | a~d或m~p任一字符(并集),等于[a-dm-p] |
[a-z&&[def]] | a~z而且是d、e、f的任一字符(交集),等于[def] |
[a-z&&[^bc]] | a~z而且不是b或c的任一字符(差集),等于[ad-z] |
[a-z&&[^m-p]] | a~z而且不是m~p的任一字符,等于[a-lq-z] |
字符类中可以再有字符类,把正则表示式想成是语言的话,字符类就像是其中独立的子语言。
预定义字符类 | 说明 |
---|---|
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
3. 贪婪、逐步、独吞量词
贪婪量词 | 说明 |
---|---|
X? | X,一次或零次 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,但是不超过 m 次 |
贪婪量词
贪婪量词之所以贪婪,是因为看到贪婪量词时,比较器(Matcher)会把剩余文字整个吃掉,再逐步吐出(Back-Off)文字,看看是否符合贪婪量词后的正则表达式。如果吐出部分符合,而吃下的部分也符合贪婪量词就比较成功,结果就是贪婪量词会尽可能地找出长度最长的符合文字。
逐步量词
如果在贪婪量词表示法后加上?,将会成为逐步量词,又称懒惰量词,或非贪婪量词,比较器看到逐步量词时,会一边吃掉剩余文字,一边看看吃下的文字是否符合正则表达式,结果就是逐步量词会尽可能地找出长度最短的符合文字。
独吞量词
如果在贪婪量词表示法后加上+,将会成为独吞量词,比较器看到独吞量词时,会先将剩余文字吃掉,然后看看独吞量词部分是否符合吃下的文字,如果符合就不会再吐出来了。
比较xfooxxxxxxfoo
规则表示式 | 得到符合的文字 |
---|---|
.*foo | xfooxxxxxxfoo |
.*?foo | xfoo与xxxxxxfoo |
.*+foo | 无 |
String[] regexs = {".*foo" , ".*?foo" , ".*+foo"};
for(String regex : regexs){
System.out.println("xfooxxxxxxfoo".replaceAll(regex,"Orz"));
}
//结果:
Orz
OrzOrz
xfooxxxxxxfoo
4. 边界比较
边界比较用来表示文字必须符合指定的边界条件,也就是定位点,因此这类表示式也常称为锚点。
边界比较 | 说明 |
---|---|
^ | 一行开头 |
$ | 一行结尾 |
\b | 单词边界 |
\B | 非单词边界 |
\A | 输入开头 |
\G | 前一个符合项目结尾 |
\Z | 并非最后终端机的输入结尾 |
\z | 输入结尾 |
5.分组与参考
可以使用()来将正则表示式分组,除了作为子正则表达式之外,还可以搭配量词使用。
例如想要验证电子邮件格式,允许的用户名称开头要是大小写英文字符,之后可搭配数字,正则表示式可以写为\^[a-zA-Z]+\d*;因为@后域名可以有数层,必须是大小写英文字符或数字,正则表示式可写成([a-zA-Z0-9]+.)+,其中使用()群组了正则表示式,之后的+表示这个群组的表示式符合一次或多次,最后要是com结尾,整个结合起来就是^[a-zA-Z]+\d*@([a-zA-Z0-9]+.)+com。
被分组的正则表示式,还可以在稍后回头参考。
在这之前,必须知道分组计数,如果有个规则表示式((A)(b(c))),其中有四个分组,这是遇到的左括号来计数。
(1) ((A)(B (C)))
(2) (A)
(3) (B (C))
(4) (C)
分组回头参考时,是在\后加上分组计数,表示参考第几个分组的比较结果。
( )、[ ]、{ } 的区别与联系
( ) 是为了提取匹配字符串的,表达式中有几个()就有几个相应的匹配字符串。(\s*)表示连续空格的字符串。
[ ] 是定义匹配的字符范围。比如[a-zA-Z0-9]表示相应位置的字符要匹配英文字符和数字。
{ } 一般是用来匹配的长度。比如\s{3}表示匹配三个空格。
圆括号()是组,主要应用在限制多选结构的范围/分组/捕获文本/环视/特殊模式处理。
- (abc|bcd|cde),表示这一段是abc、bcd、cde三者之一,顺序也必须一致。
- (abc)? 表示这一组要么一起出现,要么不出现,出现那则按顺序出现。
- (?:abc)表示找到一样abc的一组,但是不记录,不保存到变量中,否则可以通过变量中,否则可以通过x取第几个括号所匹配道德项,比如:(aaa)(bbb)(ccc)(?:ddd)(eee)可以用$1获取(aaa)匹配到的内容,而$3则获取到了(ccc)匹配到的内容,而$4则获取的是由(eee)匹配到的内容,因为前一对括号没有保存变量。
- a(?=bbb)顺序环视 表示a后面必须紧跟3个连续的b。
- (?i:xxxx)不区分大小写 (?s:.*)跨行匹配,可以匹配回车符。
方括号是单个匹配 字符集/排除字符集/命名字符集。
- [0-3],表示找到一个位置上的字符只能是0到3折四个数字,与(abc|bcd|cde)的作用比较类似,但圆括号可以匹配多个连续的字符,而一对方括号只能匹配单个字符。
- [^0-3] 表示找到这个位置上字符只能是除了0到3之外的所有字符。
- [:alnum:]代表的是[:alpha:]和[:digit:],即字母和数字;[:digit:]代表的是纯数字。
()和[]有本质的区别
() 内的内容表示的是一个表达式, () 本身不匹配任何东西,只是把括号内的内容作为同一个表达式来处理,例如 (ab){1,3} ,就表示ab一起连续出现最少1次,最多三次。如果没有括号的话,ab{1,3},就表示a 后面紧跟的b出现的最少一次,最多三次。另外,括号在匹配模式中也跟重要。
[]表示匹配字符在[]中并出现一次,并且reshuffle字符写在[]会被当成普通字符来匹配,例如 [(a)] ,会匹配 (、a、)、这三个字符。
写在最后
正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本,在日常生活是是个很方面的工具。