五分钟搞定Java正则表达式


1. 正则表达式的创建

1.1 导入包:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

1.2 创建:

//可以写成\d{3}-\d{3}-\d{4} 详情参见8
Pattern pattern = Pattern.compile("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d");
Matcher matcher = pattern.matcher("电话号码:444-555-6666 \n 电话号码:444-555-6669");

1.3 取匹配值:

while (matcher.find()) {
    System.out.println("start:"+matcher.start());//匹配到的开始位置
    System.out.println("e n d:"+matcher.end());//匹配到的结束位置
    System.out.println(matcher.group(0));//0为整个表达式结果
}

1.4 正则匹配结果输出:

start:5
e n d:17
444-555-6666
start:25
e n d:37
444-555-6669

2. 正则表达式的括号分组

2.1 创建分组:
如果想要将区号从电话号中分离,添加括号就可以在正则表达式中创建“分组”:(\d\d\d)-(\d\d\d-\d\d\d\d)

Pattern pattern = Pattern.compile("(\\d\\d\\d)-(\\d\\d\\d-\\d\\d\\d\\d)");
Matcher matcher = pattern.matcher("电话号码:444-555-6666 \n 电话号码:444-555-6669");
while (matcher.find()) {
    int count = matcher.groupCount();
    for(int i=1;i<=count;i++){//0是整个正则表达式的匹配结果,从1开始才是真正的分组结果
        System.out.println(matcher.group(i));
    }
}

2.2 正则匹配结果输出:

444 //区号
555-6666 //电话号
444 //区号
555-6669 //电话号

3. 管道匹配多个分组

3.1 "|"既是管道匹配符,管道匹配符匹配许多表达式中的一个时,就可以使用它。
如:"gaierlin And erlin!" 要匹配gaierlin及erlin两个分组中的一个

Pattern pattern = Pattern.compile("gaierlin|erlin");
Matcher matcher = pattern.matcher("gaierlin And erlin!");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

3.2 正则匹配结果输出:

gaierlin
erlin

4. 问号实现可选匹配

4.1 ?(问题)匹配零次或一次,如果想匹配的模式是可选的,则使用字符?表明它前面的分组在这个模式中是可选的。
如:"电话号码:444-555-6666 \n 电话号码:555-6669",区号是可选项匹配,即(\d\d\d-),分组(\d\d\d-)出现零次或一次

Pattern pattern = Pattern.compile("(\\d\\d\\d-)?\\d\\d\\d-\\d\\d\\d\\d");
Matcher matcher = pattern.matcher("电话号码:444-555-6666 \n 电话号码:555-6669");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

4.2 正则匹配结果输出:

444-555-6666
555-6669

5. 星号匹配零次或多次

5.1 (星号)匹配零次或多次,即星号之前的分组可以出现任意多次(零次或一次或二次或一次又一次)
如:"love、lve、abc、loove、dbc、labcve、a9ve、abve、looooove",找出所有lo
ve的所有内容。

Pattern pattern = Pattern.compile("l(o)*ve");
Matcher matcher = pattern.matcher("love、lve、abc、loove、dbc、labcve、a9ve、abve、looooove");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

5.2 正则匹配结果输出:

love
lve
loove
looooove

6. 加号匹配一次或多次

6.1 +(加号)匹配一次或多次,即加号之前的分组可以出现至少一次。
如:"love、lve、abc、loove、dbc、labcve、a9ve、abve、looooove",找出所有lo*ve的所有内容。

Pattern pattern = Pattern.compile("l(o)+ve");
Matcher matcher = pattern.matcher("love、lve、abc、loove、dbc、labcve、a9ve、abve、looooove");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

6.2 正则匹配结果输出:

love
loove
looooove

7. 花括号匹配特定次数

7.1 {}重复特定次数的分组:
(love){,5}:代表重复0到5次
(love){2,5}:代表重复2次到5次
(love){5,}:代表重复5次到更多次

如:"I you, I love you, I love love you, I love love love you, I love love love love you, I love love love love love you, I love love love love love love love love you!"

Pattern pattern = Pattern.compile("I (love ){3,5}you");
Matcher matcher = pattern.matcher("I you, I love you, I love love you, I love love love you, I love love love love you, I love love love love love you, I love love love love love love love love you!");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

7.2 正则匹配结果输出:

I love love love you
I love love love love you
I love love love love love you

8. 字符分类

8.1 在上面的实例中已经知道\d代表任意0-9的数字,像这样有缩写代码的如下表所示:只列出最常用的

缩写分类 表示
\d 0-9任意数字
\D 除0-9的数字以外的任意字符
\w 任意字母、数字、下划线字符
\W 除字母、数字、下划线以外的任意字符
\s 空格、制表符、回车换行符
\S 除空格、制表符、回车换行符以外的任意字符

再举号码:"电话号码:444-555-6666 \n 电话号码:444-555-6669"

Pattern pattern = Pattern.compile("(\\d){3}-(\\d){3}-(\\d){4}");
Matcher matcher = pattern.matcher("电话号码:444-555-6666 \\n 电话号码:444-555-6669");
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

8.2 正则匹配结果输出:

444-555-6666
444-555-6669

9. 方括号自定义字符分类

9.1 有时候\d \w \s等字符描述太宽泛,不能完成目标任务。
如:检查文件命名是否合法(在文件命名中不允许出现?*|“<>:/字符),如果包含此类字符则不合法。
此时就可以使用[]来自定义字符分类

Pattern pattern = Pattern.compile("[?*|“<>:/]");
Matcher matcher = pattern.matcher("abc*.txt");
if(matcher.find()) {
    System.out.println("文件名不合法");
}else {
    System.out.println("文件名合法");
}

9.2 正则匹配结果输出:

文件名不合法

注意:
matches() 是拿整个输入的字符串和定义的正则模式匹配;
find() 是包含匹配, 整个输入的字符串包含定义的正则模式;
自行尝试下即可知道结果

10. 通配字符

10.1 .(句点)字符在正则表达式中称为“通配符”,它是除了回车换行符之外的所有字符都可以匹配。
但是要记住通配字符只能匹配一个字符。
如:"I love you! I lo0ve you! I loove you!"

Pattern pattern = Pattern.compile("I (lo.ve) you");
Matcher matcher = pattern.matcher("I love you! I lo0ve you! I loove you!");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

10.2 正则匹配结果输出:

I lo0ve you
I loove you

11. 插入字符和美元字符

11.1 ^(插入字符)表明匹配必须发生在被查找文本开始处。
$(美元字符)表明匹配必须发生在被查找文本结束处。

如:"Hello World" 分别用匹配"Hello"、"World$"及"Hello World$"

Pattern pattern = Pattern.compile("^Hello");
Matcher matcher = pattern.matcher("Hello World");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

11.2 正则匹配结果输出:

Hello

"World$"及"^Hello World$"请自行尝试

12. 转义字符

12.1 \ (反作)字符,即为转义字符
如:"C+ C++"

  • 不添加\转义
Pattern pattern = Pattern.compile("C++");
Matcher matcher = pattern.matcher("C+ C++");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

正则匹配结果输出:

C
C
  • 添加\转义
Pattern pattern = Pattern.compile("C\\+\\+");
Matcher matcher = pattern.matcher("C+ C++");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

正则匹配结果输出:

C++

13. 用点-星匹配所有字符

13.1 匹配所有字符串(.*)
.(句点):通配符
(星号):出现0次或多次
所以(.
)既是匹配所有字符,但是换行符要除外

如:"First Name: gai LastName:erlin \n First Name: gai1 LastName:erlin1 \n First Name: g2ai LastName:2erlin"

Pattern pattern = Pattern.compile("First Name: (.*) LastName:(.*)");
Matcher matcher = pattern.matcher("First Name: gai LastName:erlin \n First Name: xxx LastName:erlin_xxx \n First Name: ooo LastName:xxx_erlin ");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

13.2 正则匹配结果输出:

First Name: gai LastName:erlin 
First Name: xxx LastName:erlin_xxx 
First Name: ooo LastName:xxx_erlin

14. 用句点字符匹配换行符

14.1 在Pattern类中有

public static Pattern compile(String regex, int flags)

方法,参数flags:正则表达式的标记模式。
所有标记模式如下表:

编译标志 解释
Pattern.CANON_EQ 当且仅当两个字符的"正规分解(canonical decomposition)"都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式"a/u030A"会匹配"?"。默认情况下,不考虑"规范相等性(canonical equivalence)"。
Pattern.CASE_INSENSITIVE (?i) 默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明感的匹配,只要将UNICODE_CASE与这个标志合起来就行了。
Pattern.COMMENTS (?x) 在这种模式下,匹配时会忽略(正则表达式里的)空格字符(注:不是指表达式里的"//s",而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。
Pattern.DOTALL (?s) 在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式'.'不匹配行的结束符。
Pattern.MULTILINE (?m) 在这种模式下,'^'和''分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,''也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
Pattern.UNICODE_CASE (?u) 在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。
Pattern.UNIX_LINES (?d) 在这个模式下,只有'/n'才被认作一行的中止,并且与'.','^',以及'$'进行匹配。

14.2 跨多行匹配举例
如:"abs \n start asdfkkie \nhello \naidnkd end" 要匹配start开始到end结束

Pattern pattern = Pattern.compile("start (.*) end$",Pattern.DOTALL);
Matcher matcher = pattern.matcher("abs \n start asdfkkie \nhello \naidnkd end");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

14.3 正则匹配结果输出:

start asdfkkie 
hello 
aidnkd end

14.4 不区分大小写举例:
如:"gaierlin And erlin! GaiErLin And ErLIN!"

Pattern pattern = Pattern.compile("(gai)*erlin",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("gaierlin And erlin! GaiErLin And ErLIN!");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

14.5 正则匹配结果输出:

gaierlin
erlin
GaiErLin
ErLIN

14.6 不区分大小写且跨多行举例:
如:"abs \n START asdfkkie \nhello \naidnkd END \nstart abc \n defg\n ffff end"

public static Pattern compile(String regex, int flags)

compile方法的flags只接受一个参数,如果要使用两个以上的标记编译正则怎么实现?
答案是:使用|即:Pattern.CASE_INSENSITIVE|Pattern.DOTALL

Pattern pattern = Pattern.compile("start (.*) end",Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
Matcher matcher = pattern.matcher("abs \\n START asdfkkie \\nhello \\naidnkd END \\n start abc \\n defg\\n ffff end");
while (matcher.find()){
    System.out.println(matcher.group(0));
}

14.7 正则匹配结果输出:

START asdfkkie \nhello \naidnkd END \n start abc \n defg\n ffff end

15. 如何让别人更好的理解你所写的正则表达式

15.1 如:javatianxia@163.com 验证邮箱为例

Pattern pattern = Pattern.compile(
        "^\\w+(\\.\\w+)?" + //邮件登录名
        "\\@\\w+" +         //主机名
        "\\.(\\w+){2,4}"    //域名
);
Matcher matcher = pattern.matcher("javatianxia@163.com");
if (matcher.matches()) {
    System.out.println("合法");
} else {
    System.out.println("不合法");
}

看到这里想必都已经明白了,就是对正则表达式添加注释。

15.2 正则匹配结果输出:

合法
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • RegExp 三大方法本文的RegExp采用直接量语法表示:/pattern/attributes。attribu...
    恩德_b0c2阅读 455评论 0 0
  • Python中的正则表达式(re) import rere.match #从开始位置开始匹配,如果开头没有则无re...
    BigJeffWang阅读 7,064评论 0 99
  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,141评论 0 9
  • 注:本篇文章只为方便查看,特此保留,如有冒犯,敬请谅解!!! 本文目标 30分钟内让你明白正则表达式是什么,并对它...
    阿杰Alex阅读 1,479评论 0 10
  • 版本:v2.3.5 (2017-6-12) 作者:deerchao 转载请注明来源 目录 跳过目录 本文目标 如何...
    readilen阅读 951评论 2 13