java正则、捕获组
1.正则概念
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
2.正则表达式的规则
> 1、任意一个字符表示匹配任意对应的字符,如a匹配a,7匹配7,-匹配-。
>
> 2、[]代表匹配中括号中其中任一个字符,如[abc]匹配a或b或c。
>
> 3、-在中括号里面和外面代表含义不同,如在外时,就匹配-,如果在中括号内[a-b]表示匹配26个小写字母中的任一个;[a-zA-Z]匹配大小写共52个字母中任一个;[0-9]匹配十个数字中任一个。
>
> 4、^在中括号里面和外面含义不同,如在外时,就表示开头, ^ 7[0-9]表示匹配开头是7的,且第二位是任一数字的字符串;如果在中括号里面,表示除了这个字符之外的任意字符(包括数字,特殊字符),如[^abc]表示匹配出去abc之外的其他任一字符。
> 5、.表示匹配任意的字符。
> 6、\d表示数字。
> 7、\D表示非数字。
> 8、\s表示由空字符组成,[ \t\n\r\x\f]。
> 9、\S表示由非空字符组成,[^\s]。
> 10、\w表示字母、数字、下划线,[a-zA-Z0-9_]。
> 11、\W表示不是由字母、数字、下划线组成。
> 12、?: 表示出现0次或1次
> 13、+表示出现1次或多次。
> 14、*表示出现0次、1次或多次。
> 15、{n}表示出现n次。
> 16、{n,m}表示出现n~m次。
> 17、{n,}表示出现n次或n次以上。
> 18、XY表示X后面跟着Y,这里X和Y分别是正则表达式的一部分。
> 19、X|Y表示X或Y,比如"food|f"匹配的是foo(d或f),而"(food)|f"匹配的是food或f。
> 20、 (X)子表达式,将X看做是一个整体。
3.如何使用正则表达式
3.1 匹配
1). 实现方式1,匹配一个数字。
/**
* 匹配一个数字
*/
public void regex1(){
String str = "8";
String regex = "[0-9]";
boolean flag = Pattern.matches(regex,str);
System.out.println(flag);
}
2). 实现方式2, 匹配3个到5个字母,大小写不限,包括3和5个。
/**
* 匹配3到5个字母
*/
public void regex2(){
String str = "hello";
String regex = "[a-zA-Z]{3,5}";
boolean flag = Pattern.matches(regex,str);
System.out.println(flag);
}
3). 实现方式3(此种实现方式最快), 匹配11位的电话号码,匹配规则:第一个数字是1,第二个数字是2,3,7,8中任一个,后面9位数字中不包含4。
/**
* 匹配11位的电话号码,匹配规则:第一个数字是1,第二个数字是2,3,7,8中任一个,后面9位数字中不包含4。
*/
public void regex3(){
String str = "13656231253";
String regex = "1[2378][0-35-9]{9}";
boolean flag = Pattern.matches(regex,str);
System.out.println(flag);
}
4)正则必须包含字母数字下划线,长度至少8位
思路:排除法
1、排除大写字母、小写字母、数字、特殊符号中1种组合、2种组合、3种组合,那么就只剩下4种都包含的组合了
2、表达式为:^(?![A-Za-z0-9]+)(?![A-Za-z\W]+)[a-zA-Z0-9\W]{8,}$
3、拆分解释:其中(2)-(6)运用了零宽断言、环视等正则功能
(1)^匹配开头
(2)(?![A-Za-z0-9]+$)匹配后面不全是(大写字母或小写字母或数字)的位置,排除了(大写字母、小写字母、数字)的1种2种3种组合
(3)(?![a-z0-9\W]+$)同理,排除了(小写字母、数字、特殊符号)的1种2种3种组合
(4)(?![A-Za-z\W]+$)同理,排除了(大写字母、小写字母、特殊符号)的1种2种3种组合
(5)(?![A-Z0-9\W]+$)同理,排除了(大写字母、数组、特殊符号)的1种2种3种组合
(6)[a-zA-Z0-9\W]匹配(小写字母或大写字母或数字或特殊符号)因为排除了上面的组合,所以就只剩下了4种都包含的组合了
(7){8,}8位以上
(8)$匹配字符串结尾
代码:
//大小写字母数字下划线4选4,且至少8位
private final String regex4 = "^(?![A-Z0-9\\W_]+$)(?![a-z0-9\\W_]+$)(?![a-zA-Z\\W_]+$)(?![a-zA-Z0-9]+$)[a-zA-Z0-9\\W_]{8,}$";
//大小写字母数字下划线4选3,且至少8位
private final String regex4To3 = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,}$";
//大小写字母数字下划线,且至少8位
private final String regexAll = "[a-zA-Z0-9\\W_]{8,}";
/**
* 正则必须包含字母数字下划线,长度至少8位
* @param str1
* @return
*/
public boolean regex5(String str1){
boolean flag = false;
flag = Pattern.matches(regex4,str1);
return flag;
}
3.2 替换
1)简单替换
/**
* 替换数字、字母
*/
public void regex4(){
String str = "12ab8cde9fg0";
String regex1 = "[a-zA-Z]";
String regex2 = "\\d+";
String regex1Replace = str.replaceAll(regex1,".");
String regex2Replace = str.replaceAll(regex2,"*");
System.out.println(regex1Replace);
System.out.println(regex2Replace);
}
4 、捕获组
捕获组分为:
普通捕获组(Expression)
命名捕获组(?Expression)
普通捕获组
从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。
对于时间字符串:2017-04-25,表达式如下
(\\d{4})-((\\d{2})-(\\d{2}))
有 4 个左括号,所以有 4 个分组:
编号 | 捕获组 | 匹配 |
0 | (\d{4})-((\d{2})-(\d{2})) | 2017-04-25 |
1 | (\d{4}) | 2017 |
2 | ((\d{2})-(\d{2})) | 04-25 |
3 | (\d{2}) | 04 |
4 | (\d{2}) | 25 |
代码
public void regex6(){
//捕获组
String DATE_STRING = "2017-04-25";
String P_COMM = "(\\d{4}-((\\d{2})-(\\d{2})))";
Pattern pattern = Pattern.compile(P_COMM);
Matcher matcher = pattern.matcher(DATE_STRING);
matcher.find();//必须要有这句
System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
System.out.printf("\nmatcher.group(1) value:%s", matcher.group(1));
System.out.printf("\nmatcher.group(2) value:%s", matcher.group(2));
System.out.printf("\nmatcher.group(3) value:%s", matcher.group(3));
System.out.printf("\nmatcher.group(4) value:%s", matcher.group(4));
}
命名捕获组
每个以左括号开始的捕获组,都紧跟着 ?,而后才是正则表达式。
对于时间字符串:2017-04-25,表达式如下:
(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<date>\\d{2}))
命名的捕获组同样也可以使用编号获取相应值。
public void regex7(){
String DATE_STRING = "2017-04-25";
String P_COMM = "(?<year>\\d{4})-(?<md>(?<mm>\\d{2})-(?<dd>\\d{2}))";
Pattern pattern = Pattern.compile(P_COMM);
Matcher matcher = pattern.matcher(DATE_STRING);
matcher.find();//必须要有这句
System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
System.out.printf("\nmatcher.group(1) value:%s", matcher.group("year"));
System.out.printf("\nmatcher.group(2) value:%s", matcher.group("md"));
System.out.printf("\nmatcher.group(3) value:%s", matcher.group("mm"));
System.out.printf("\nmatcher.group(4) value:%s", matcher.group("dd"));
}