正则表达式

正则表达式

1. 正则表达式

1.1. 概述

​ 在日常对一些软件的使用,经常会遇到:用户输入手机号,对手机号的格式验证;需要从一段字符串中截取满足条件的字串,此时需要做匹配查找;在一些特定场景下需要将输入的内容中包含的敏感词替换成其他等需求;因此对字符串的一些特殊处理包括:验证,查找,替换等。针对这些需求目前在开发领域有意向技术可以满足需求:正则表达式(Regex)。

正则表达式最早源自于perl语言,后来广泛的被其他(c,c++,java,c#,javascript…)语言接受;java中对于正则表达式提供了几个常用类:

  • java.lang.String
  • java.util.regex.Pattern
  • java.util.regex.Matcher

1.2. 元字符匹配

元字符匹配即对单个的字符内容匹配,正则表达式中包含以下常见的符号实现匹配规则

元字符说明
.匹配除换行符以外的任意字符
\w匹配字母或数字
\s匹配任意的空白符(空格,制表符,换行)
\d匹配数字
\b匹配单词的开始或结束
\W匹配非单词字符(非字母,非数字)
\S匹配非空白字符
\D匹配非数字
^匹配字符串的开始
$匹配字符串的结束
[0-9]匹配数字
[a-zA-Z]匹配字母
[^0-9]匹配非数字

1.3. 长度匹配

长度匹配指的是需要匹配的字符串长度

语法说明
*重复零次或更多次
+重复一次或更多次
重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
{0,n}重复0次或者n次

1.4. Pattern&Matcher

通过对String类中matches方法了解,可以看出来该方法的实现是基于java.util.regex.Patternjava.util.regex.Matcher类来合作完成。

Pattern是正则表达式的编译表达形式,在java中正则表达式需要产生效果,一般是需要先经过编译环节,才能具体使用:

Pattern p = Pattern.compile(正则表达式);

Matcher:使用Pattern完成编译之后,将会产生一个匹配模式对象,接下来就可以通过对固定的字符串匹配获取匹配器:

Matcher m = p.matcher(目标字符串);

匹配器包含三个主要功能:

  • matches 方法尝试将整个输入序列与该模式匹配。
  • lookingAt 尝试将输入序列从头开始与该模式匹配。
  • find 方法扫描输入序列以查找与该模式匹配的下一个子序列。

1.5. 分组

在正则表达式编写时可以对表达式内部的子串进行分组匹配,例如以下表达式:

(a(b(c)))

包含如下分组:

  • 第0组(a(b(c)))
  • 第1组a(b(c))
  • 第2组(b(c))
  • 第3组(c)
String regex = "(\\w(\\w(\\w)))";
String str = "abc";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
m.find();

System.out.println("第0组:"+m.group(0)); // abc
System.out.println("第1组:"+m.group(1)); // abc
System.out.println("第2组:"+m.group(2)); // bc
System.out.println("第3组:"+m.group(3)); // c

1.6 三种匹配模式

1.6.1. 贪婪模式(greedy)

贪婪模式即尽可能多的匹配,使用+符号,例如:

String s = "abbcccccsfsdccc";
String regex = "a\\w+c";

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
while(m.find()){
    System.out.println(m.group());
}

运行结果:

abbcccccsfsdccc

1.6.2. 勉强模式(reluctant)

勉强模式也称之非贪婪模式,使用是最短匹配,符号?,例如:

String s = "abbcccccsfsdccc";
String regex = "a\\w+?c";

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
while(m.find()){
    System.out.println(m.group());
}

运行结果:

abbc

1.6.3. 独占模式(possessive)

独占模式跟贪婪模式的区别在于,不会回溯,即一直往后搜索会将后续的所有字符串进行匹配

String s = "aabbbccddcaabbbdd";
String regex = "aa.*+dd";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
m.find();
System.out.println(m.group());

结果:

Exception in thread "main" java.lang.IllegalStateException: No match found
	at java.util.regex.Matcher.group(Unknown Source)
	at java.util.regex.Matcher.group(Unknown Source)
	at com.softeem.lesson20.regex.ReluctantDemo.main(ReluctantDemo.java:27)

1.7 正则表达式补充(后向引用)

正则表达式提供的后向允许使用()对表达式分组之后,使用$编号方式引用表达式所匹配的内容,例如:手机号脱敏操作

  • 输入手机号:13854678954
  • 输出手机号:138****8954

使用后向引用方式,只需一行代码即可:

String phone = "13854678954".replaceAll("(1\\d{2})\\d{4}(\\d{4})","$1****$2");

后向引用可以结局很多数据格式转换问题:

//有一个日期 2021-7-22 显示为 2021年7月22日
System.out.println("2021-7-22".replaceAll("(\\d{4})-(\\d{1,2})-(\\d{1,2})","$1年$2月$3日"));

//以上问题传统的解决方法
String sDate = "2021-07-22";
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
Date date = fmt.parse(sDate);
fmt = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(fmt.format(date));

//有一个日期 2021-7-22 09:06:33 显示为 2021年7月22日 09时06分33秒
regex = "(\\d{4})-(\\d{1,2})-(\\d{1,2})\\s+?(\\d{1,2}):(\\d{1,2}):(\\d{1,2})";
System.out.println("2021-7-22 09:06:33".replaceFirst(regex,"$1年$2月$3日 $4时$5分$6秒"));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值