Java – 正则表达式

简介

本文讲解Java 中正则表达式的使用和注意事项

正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性。

本篇文章中分别使用正则表达式进行文本判断,和信息提取。

 

正则表达式基本规则

单个字符匹配规则表

表达 说明 举例 结果
[abc] 在单个字符上匹配中括号内的字符 [abc] 只能是a,b或c
[^] 在单个字符上匹配中括号内的字符 [^abc] 不能是a,b或c
[a-zA-Z] a到z,A到Z [a-zA-Z] a-Z 都可匹配
[a-d[m-p]] a到d,或m-p都可被匹配 [a-d[m-p]] a到d,或m-p
[a-z&&[def]] a-z中和d,e,f的交集 [a-z&&[def]] def
[a-z&&[^bc]] a-z中不是b和c的字母 [a-z&&[^bc]] ad-z
[a-z&&[^m-p]] a-z中除了m到p的交集 [a-z&&[^m-p]] [a-lq-z]

 

预定义字符规则表

 

表达 说明 举例 结果
 . 任意字符,不包括回车 \n  . a-Z0-9!-)
[] 里面的内容匹配一次,可配合数量词定位数量  [0-9] 0123456789
() 分组  a(bc)+ abcbcbcbc都可以
^ 取反  ^a 除a以外都可以
&& 交集,不能写单个&,否则会被认为是普通字母 & abc&&b abc中要和b一样的=>结果b
| 写在方括号外面表示并集(或) x|X x和X都可以
\ 转义字符 \\ =>\
(?i) 字母不分大小写 (?i)abc

a((?i)b)c

abc,Abc,ABc,ABC,AbC,aBc等都可以

只能允许b可以大小写不分

\d 一个数字 \d 0-9
\D 非数字 \D 不是数字都可以
\s 一个空白字符 \s [\t\n\x0B\f\r]
\S 非空白字符 \S [^\s]
\w [a-zA-Z0-9_] 英文、数字、下划线 \w a-z,A-Z,0-9,和_
\W 和[^a-zA-Z0-9_],非英文、非数字、非下划线 \W [^\w]

 

数量词规则

表达 说明 举例 结果
 ? 一次或0次   [a]. a不出现或出现1次
 * 0次或多次   [a]* a不出现或出现多次
 + 一次或多次   [a]+ a至少出现一次,也可出现多次
 {n} 正好n次   [a]{3} a正好出现3次
 {n,} 至少n次以上   [a]{2,} a至少出现2次以上
 {n,m} 至少n次以上,m次以下   [a]{2,5} a到少出现2次,但不超过5次

 

String 类相关正则方法

matches 正则判断

在String 实例中,有一个方法 matches(String regex) , 可以传入正则表达式字符串来判断这个String实例中是否符合正则规则,如果符合返回 true , 否则返回 false

String a = "abcdefg";
boolean matches = a.matches("\\w+");
System.out.println(matches);  // => true \\w指 a-zA-Z0-9_,字符串中 a 包含这些字母


String a = "abcdefg";
boolean matches = a.matches("\\d+");
System.out.println(matches);  // => false  \\d 表示 0-9,而a字符串中并没有数字0-9

 

replaceAll() 使用正则方法替换

 

String 类中提供一个文本替换的功能,且这个替换功能支持正则表达式

String s = "用户名aaaa密码aaaa性别"
s.replaceAll("a+","替换文本");

 

 

split() 使用正则方法分割文本

String 类中提供一个文本分割的功能,且这个分割功能支持正则表达式

String s = "用户名aaaa密码aaaa性别"
s.split("a+");  // => {用户名,密码,性别}

 

 

Pattern 和 Matcher

通过使用Pattern类来进行匹配,再使用Matcher来进行取值。

Pattern是管理正则表达式的类,用它来生成一个带有正则表达式的对象

Matcher是一个文本匹配器,作用是按照正则表达式对象的规则去读取字符串,Java默认从头开始读取。

创建Pattern正则对象

创建Pattern正则对象不需要使用 new,只需要调用静态方法 compile 方法就可以了,并传入正则字符串

Pattern compile = Pattern.compile("\\w+");

 

 

创建Matcher文本匹配器

Matcher文本匹配器在匹配字串时需要提供正则对象,上面我们通过 Pattern.compile("\\w+"); 申请了一个正则对象,接下来可以使用Matcher文本匹配器匹配我们想要的字符串

String a = "abcdefghijklmn";
Matcher m = p.matcher( str )

通过调用正则对象的 matcher 方法取得 Matcher 对象

 

 

find() 查找符合字串

通过调用Matcher 实例对象的 find() 方法,指向字串中的匹配项,若找到匹配项,返回 true,每调用一次,则在上一次匹配的位置上,继续往下寻找匹配,直至找不到为止,则返回false

boolean isFind = m.find();  // => 如果找到返回 true , 否则返回 false

在底层中,届果 find() 找到的话,会记录该匹配项的起始索引和结束索引+1,因为 substring() 方法中,就是取出起始索引和结束索引+1的位置文本。

 

 

group() 取得匹配字串

find() 方法让我们能在字符串中找到匹配项的位置,而group() 方法,则是取出字符串中匹配的文本。

通过调用 Matcher 对象的group() 方法即可拿到当前 find() 方法寻找到的匹配项。

String str = m.group();

 

 

通过循环匹配所有项

Pattern compile = Pattern.compile("\\w+");
Matcher m = compile.matcher(string );
while (m.find()){
     System.out.println(m.group());
}

 

 

贪婪爬取

贪婪爬取指的是,希望能多匹配一些的话就多匹配一些,举例子

String s = "abbbbbbbbbbbccccccccccc"
使用 ab+ 规则取出匹配项

如果使用贪婪爬取,那么我们最后得到的结果是

 

“abbbbbbbbbbb”

Java默认使用的是贪婪爬取,其正则如下(省略Pattern操作)

String s = "abbbbbbbbbbbccccccccccc"
String regex = "ab+"

 

 

 

 

非贪婪爬取

非贪婪爬取和贪婪爬取刚好相反,也就是说,当Java找到适合的匹配后,就停止继续匹配了,举

String s = "abbbbbbbbbbbccccccccccc"
使用 ab+ 规则取出匹配项(非贪婪爬取)

如果使用非贪婪爬取,那么我们最后得到的结果是

“ab”

如果我们需要使用 非贪婪爬取,我们只需要在正则规则+,* 之类的数量词后面加 "? ",如下(省略Pattern操作)

String s = "abbbbbbbbbbbccccccccccc"
String regex = "ab+?"

 

匹配分组

捕获分组

假如我们需要使用定义过的正则表达式时,我们可以通过调用分组的方式复用之前定义过的正则。

分组使用小括号定义。

规则

1.从1开始,连续不间断

2.以左括号为基准,最左边的是第一组,其次为第二组,以此类推

(\\d+)(\\w+)(\\s+);  
// => 第一组为 (\\d+)
// => 第二组为 (\\w+)
// => 第三组为 (\\s+)

 

 

(\\d+(\\w+))(\\s+)
// => 第一组为 (\\d+(\\w+))
// => 第二组为 (\\w+)
// => 第三组为 (\\s+)

 

 

举例,

匹配 aaa123aaa , bb445bb , &467&

我们知道,上面三个的规律是,前后是一样的,前面的字母匹配,我们可以使用 (.+) 就能把 aaa, bb, & 给匹配上了,因为我们做了分组,所以这里的 (.+) 是一组,我们可以通过使用 \\1 来取得这一组的定义,如下

String regex = "(.+).+\\1"

(.+) 开头有多个任意字符,并设为一个分组

.+ 中间有一个或多个任意字符

\\1  调用第一个分组的定义,也就是 (.+)

 

我们再来举一个例子:

String regex = "((.)\\2*).+\\1"

(.)   指的是有一个任意字符

\\2  在此列中,因为 (.) 在另一个括号内,因此它是第2组了,所以 \\2 指的是 (.)

*   作用于 \\2 表示 \\2 有0或多个

((.)\\2*)   表示 (.) 作为一个组,且组在第二组,并且认为这个组中有0到多个

.+  中间的任意字符

\\1  调用第一组,即 ((.)\\2*)

 

外部使用分组

内部使用分组时,我们使用 \\ 号进行调用,而如果需要在外部调用分组的话,我们可以使用 $ 符调用就可

String s = "aaabbbbbbbbcdddd"
s.replaceAll("(.)\\1+", "$1" );
// => 会匹配出四个项 [aaa],[bbbbbbbb],[c],[dddd]
// => 最后会把 aaa->a, bbbbbbbb->b, c->c, dddd->d
// => abcd

(.)\\1+ 表示有一个或多个第一组的任意字符定义

 

$1  表示在外部使用 (.)

 

非捕获分组

当我们使用捕获分组时,我们需要使用 () 来进行分组,但是有时候我们需要 () 并不是因为我们需要分组,而仅仅只是缩小匹配范围,如

[(a|b)(c|d)] 这里的(a|b)仅仅是为了缩小到a或b的匹配,如果不加 () ,那么 | 号或会以全局的方式进行匹配,但加了 () 后, (a|b) 则占用了一个分组,而我们并不想它占用分组名额时,我们可以使用非捕获分组定义,定义如下

表达 说明 举例 结果
 (?:正则) 获取所有 Java(?:8|11|17) Java8,Java11,Java17
 (?=正则) 获取前面部分 Java(?=8|11|17) Java,Java,Java
 (?!正则) 获取不是指定内容的前面部分 Java(?!8|11|17) 8,11,17

 

如果您喜欢本站,点击这儿不花一分钱捐赠本站

这些信息可能会帮助到你: 下载帮助 | 报毒说明 | 进站必看

修改版本安卓软件,加群提示为修改者自留,非本站信息,注意鉴别

THE END
分享
二维码
打赏
海报
Java – 正则表达式
本文讲解Java 中正则表达式的使用和注意事项
<<上一篇
下一篇>>