文章目录

  • 一、正则表达式
  • 1.1 正则表达式中的特殊字符
  • 1.2 正则表达式所支持的合法字符
  • 1.3 方括号表达式
  • 1.4 边界匹配符
  • 1.5 三种模式的数量表示符
  • 二、应用
  • 2.1 String 类
  • 2.2 Pattern 类和 Matcher 类


一、正则表达式

1.1 正则表达式中的特殊字符

特殊字符

说明

$

匹配一行的结尾。要匹配 $ 字符本身,请使用\$

^

匹配一行的开头。要匹配 ^ 字符本身,请使用\^

()

标记子表达式的开始和结束位置。要匹配这些字符,请使用\(\)。将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。

[]

用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\[\]

{}

用于标记前面子表达式的出现频度。要匹配这些字符,请使用\{\}

{n}

n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。

{n,}

n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。

{n,m}

mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

*

指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用\*。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。

+

指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用\+。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。

?

指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用\?。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。

.

匹配除换行符\n\r之外的任何单字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。要匹配.字符本身,请使用\.

\

用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\\

|

指定两项之间任选一项。如果要匹配字符本身,请使用\|

((A)(B(C))):第一组 ((A)(B©)) 第二组 (A) 第三组(B©) 第四组©

1.2 正则表达式所支持的合法字符

字符

解释

\d

匹配 0~9 的所有数字

\D

匹配非数字

\s

匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等

\S

匹配所有的非空白字符

\w

匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_

\W

匹配所有的非单词字符

\0mnn

八进制数 0mnn 所表示的字符

\xhh

十六进制值 0xhh 所表示的字符

\uhhhh

十六进制值 0xhhhh 所表示的 Unicode 字符

\t

制表符(“\u0009”)

\n

新行(换行)符(‘\u000A’)

\r

回车符(‘\u000D’)

\f

换页符(‘\u000C’)

\a

报警(bell)符(‘\u0007’)

\e

Escape 符(‘\u001B’)

\cx

x 对应的的控制符。例如,\cM匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。

  • d 是 digit 的意思,代表数字。
  • s 是 space 的意思,代表空白。
  • w 是 word 的意思,代表单词。
  • d、s、w 的大写形式恰好匹配与之相反的字符。

1.3 方括号表达式

方括号表达式

说明

表示枚举

例如[abc]表示 a、b、c 其中任意一个字符;[gz]表示 g、z 其中任意一个字符

表示范围:-

例如[a-f]表示 a~f 范围内的任意字符;[\\u0041-\\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如[a-cx-z],表示 ac、xz 范围内的任意字符

表示求否:^

例如[^abc]表示非 a、b、c 的任意字符;[^a-f]表示不是 a~f 范围内的任意字符

表示“与”运算:&&

例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、e f[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外 [ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符

表示“并”运算

并运算与前面的枚举类似。例如[a-d[m-p]]表示 [a-dm-p]

[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]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)

1.4 边界匹配符

边界匹配符

说明

^

行的开头

$

行的结尾

\b

单词的边界

\B

非单词的边界

\A

输入的开头

\G

前一个匹配的结尾

\Z

输入的结尾,仅用于最后的结束符

\z

输入的结尾

1.5 三种模式的数量表示符

表达式支持的数量标识符有如下几种模式。

  • Greedy(贪婪模式):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。如果你发现表达式匹配的结果与预期的不符,很有可能是因为你以为表达式只会匹配前面几个字符,而实际上它是贪婪模式,所以会一直匹配下去。
  • Reluctant(勉强模式):用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。
  • Possessive(占有模式):用加号后缀(+)表示,目前只有 Java 支持占有模式,通常比较少用。

贪婪模式

非贪婪模式

占用模式

说明

X?

X??

X?+

X表达式出现零次或一次

X*

X*?

X*+

X表达式出现零次或多次

X+

X+?

X++

X表达式出现一次或多次

X{n}

X{n}?

X{n}+

X表达式出现 n 次

X{n,}

X{n,}?

X{n,}+

X表达式最少出现 n 次

X{n,m}

X{n,m}?

X{n,m}+

X表达式最少出现 n 次,最多出现 m 次

关于贪婪模式和非贪婪模式的对比,看如下代码:

String str = "hello,java!";
// 贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*" , "■"));    //输出■,java!
// 非贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*?" , "■""));    //输出■hello, java!

二、应用

2.1 String 类

String 类里也提供了如下几个特殊的方法。

  • boolean matches(String regex):判断该字符串是否匹配指定的正则表达式。
  • String replaceAll(String regex, String replacement):将该字符串中所有匹配 regex 的子串替换成 replacement。
  • String replaceFirst(String regex, String replacement):将该字符串中第一个匹配 regex 的子串替换成 replacement。
  • String[] split(String regex):以 regex 作为分隔符,把该字符串分割成多个子串。

2.2 Pattern 类和 Matcher 类

除此之外,Java 还提供了 Pattern 和 Matcher 两个类专门用于提供正则表达式支持。

  • 匹配
// 编译正则表达式,这样子可以重用模式。
Pattern p = Pattern.compile("a*b");
// 用模式检查字符串
Matcher m = p.matcher("aaaaab");
// 检查匹配结果
boolean b = m.matches();

// 等价于(简化)
boolean b = Pattern.matches("a*b", "aaaaab"); 
// 等价于(简化)
boolean b = "aaaaab".matches("a*b");

注意:在java中,需要 " \ "的匹配符,需要加多一个 " \ " 进行转义。比如匹配\d在java中要写成\\d。

  • 获取
String name = "13800138000" ;
String regex ="(\\d{3})(\\d{4})(\\d{4})" ;
Pattern pattern  = Pattern.compile(regex);
Matcher matcher = pattern.matcher(name);
String result = null;
if(matcher.find()) { //如果需要取所有,可以使用while
    //取第二组的数据。
    result = matcher.group(2);
}