正则表达式
- 是什么: 正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
- 干什么:正则主要用于字符串中 为方便字符串操作 ,很多地方不使用正则表达式也能达到目的,但是可能麻烦很多。
- 怎么用:在java中的标准使用如下:
//编译正则表达式,这样子可以重用模式。Pattern p=Pattern.compile("a*b");// 用模式检查字符串Matcher m= p.matcher("aaaaab");//检查匹配结果boolean b= m.matches();
上面的使用太繁琐,一般使用场景我们只需要匹配检查一次即可。所以可以省略为如下方式:
boolean b = Pattern.matches("a*b", "aaaaab");
另外正则运用在字符串上,上面那样普通使用还是麻烦,因此在字符串对象里提供快速调用的方法(matches/split/replace), 如上面的matches只需要这样:
"aaaaab".matches("a*b")
字符串matches和Pattern.matches的源码如下,可以发现其实内部还是用了第一种方式的。
//String对象成员matches方法publicbooleanmatches(String regex){returnPattern.matches(regex,this);}//Pattern的matches方法publicstaticbooleanmatches(String regex,CharSequence input){Pattern p=Pattern.compile(regex);Matcher m= p.matcher(input);return m.matches();}
- 字符串的操作主要有四种,匹配、切割、替换、获取,我们接下来分别说明,其中涉及到 “组” 的概念。
一,匹配
- 匹配规则, 如:
#字符类[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](减去)
- 更多具体的匹配规则可以在 java.util.regex.Pattern 的文档里找到, 这些规则基本是通用的.即,其他语言的也是这样子的形式. 另外在java中,需要 " \ "的匹配符,需要加多一个 " \ " 进行转义.
- 匹配规则是基础, 先匹配, 才能对匹配进行切割,替换,获取操作
- 常见如检查匹配邮箱,手机号码等. 简单检查匹配手机号码如下:
String regex="1[358]\\d{9}";boolean flag="15322510408".matches(regex);
二,切割
String[] str = string.split(regex) ;
如下简单例子:
//按一个或多个空格切割String name="aaaaa _haha";String regex=" +";String[] strs= name.split(regex);
- 例子2: 根据重复的字符进行切割, 例如.
"abctttttttcdemmmmmmfglllllll-------"
切割结果为[abc,cde,fg]
, 这里就需要引入组的概念了.
- 组: 可以简单理解为, 把匹配的规则 当成一个变量 来使用 ,组的概念大部分也是通用的.- 用"()" 即定义了一个匹配组
- 捕获组可以通过从左到右计算其开括号来编号. 例如,在表达式regex中
((A)(B(C)))
中,存在四个这样的组:((A)(B(C)))
(A)
(B(C))
(C)
- 编号为0的组代表整个表达式. 可以理解为, 组的号码是从1开始, 并且从左到右增加,
- 要使用到组,引用组方式:
\\1
(第一个\
用来转义)或者$1
。因此上面按重复切割代码如下: - 组的另外说明:在regex里用
\\1
引用,不在regex用$1
引用,如:String[] strs = name.split("(.)\\1+")
和String result = name.replaceAll("(\\d{3})", "$1")
//按重复字符切割String name="abctttttttcdemmmmmmfglllllll-------";String regex="(.)\\1+";String[] strs= name.split(regex);
三,替换
- 字符串中的替换方法如下:
string.replace(char oldChar, char newChar)
和string.replace(CharSequence target, CharSequence replacement)
替换单个字符,不使用到正则string.replaceAll(String regex, String replacement)
替换字符串,使用到正则string.replaceFirst(String regex, String replacement)
替换匹配的第一个字符串,使用到正则
- 替换也有组的概念, 例如,要将上面的重复字符替换为单个字符,即结果为
abctcdemfgl-
, 代码如下
String name="abctttttttcdemmmmmmfglllllll-------";String regex="(.)\\1+";String result= name.replaceAll(regex,"$1");
- 还有,把手机号码的中间思维替换为****, 做法类似。
- 方法1:分成三组
String name="13800138000";String regex="(\\d{3})(\\d{4}) (\\d{4})";String result= name.replaceAll(regex,"$1****$3");
- 方法2:分成两组
String name="13800138000";String regex="(\\d{3})\\d{4}(\\d{4})";String result= name.replaceAll(regex,"$1****$2");
四,获取
获取的方式,string对象里没有直接支持。因此要直接使用到Pattern和Matcher对象
做法如下:
- 获得pattern对象,pattern静态方法
complie
返回pattern对象 - pattern 的
matcher
方法返回matcher匹配器对象 - [可选操作] 调用 matcher对象 的 matches(str)返回true或false以此来判断是否有匹配的字符串
matcher.find()
, 指针会移动到下一个匹配的字符串,如果有返回true. 通过**matcher.group();
**等方法 获取当前指针匹配的字符串- find方法说明文档:尝试查找与该模式匹配的 < 输入序列的下一个子序列 >。 此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。
- 获得pattern对象,pattern静态方法
例如上面要获取手机号码中间四位。
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);}
p.s 正则在java等的api文档中写得很详细了,有什么细节,例如匹配规则等建议直接看文档,会更详细,