一、正则表达式语法
1、计数符(以下n和m为非负整数,且m>n)
- *,匹配0次或多次,即{0,};
- +,匹配1次或多次,即{1,};
- ?,匹配0次或1次,即{0,1};
- {n},匹配n次;
- {n,},匹配至少n次;
- {n,m},匹配至少n次,至多m次。
2、定位符
- ^,以什么起始
- $,以什么结尾
- \b,以什么起始或以什么结尾,用法等同^或$其中之一
- \B,不以此为起始或结尾
//匹配出开始的"m18",等同于"\\bm(\\d+)"
Pattern pattern = Pattern.compile("^m(\\d+)", Pattern.CASE_INSENSITIVE);
//匹配出结尾的"m54",等同于"m(\\d+)\\b"
Pattern pattern2 = Pattern.compile("m(\\d+)$", Pattern.CASE_INSENSITIVE);
String line2 = "m18m62m54";
Matcher matcher2 = pattern2.matcher(line2);
//匹配出不是结尾的组合"m18","m62","m5"
Pattern pattern2 = Pattern.compile("m(\\d+)\\B", Pattern.CASE_INSENSITIVE);
String line2 = "m18m62m54";
Matcher matcher2 = pattern2.matcher(line2);
while (matcher2.find()) {
System.out.println(matcher2.group());
}
//匹配出不是开头的组合"m62","m54"
Pattern pattern2 = Pattern.compile("\\Bm(\\d+)", Pattern.CASE_INSENSITIVE);
String line2 = "m18m62m54";
Matcher matcher2 = pattern2.matcher(line2);
int count = Stream.iterate(0,integer -> integer+1).filter(integer -> !matcher2.find()).findFirst().get();
System.out.println(count);
3、转义符(“\”)
对于表达式中的特殊符号,如果需要使用其符号本身(而非特殊含义),则需要在前面加转义符
//匹配出数字符号组合"16$"
Pattern pattern1 = Pattern.compile("\\d+\\$", Pattern.CASE_INSENSITIVE);
String line = "价格 16$,库存 20件";
Matcher matcher = pattern1.matcher(line);
//匹配出结尾的数字"16"
Pattern pattern2 = Pattern.compile("\\d+$", Pattern.CASE_INSENSITIVE);
String line2 = "mode=18ms TTL=16";
Matcher matcher2 = pattern2.matcher(line2);
4、脱字符
非某个字符的其他字符,一般用"[^一个字符或多个字符]"表示,如[^>@],即不是>也不是@符号的其他字符
//匹配出<m18m62m54>
Pattern pattern2 = Pattern.compile("^<([^>]+)>", Pattern.CASE_INSENSITIVE);
String line2 = "<m18m62m54>275</div>";
Matcher matcher2 = pattern2.matcher(line2);
注意:脱字符只能单个字符的判断,不能进行多个字符的字符串整体判断,需要做字符串判断则要用到断言"(?!字符串)" 零宽负向先行断言或"(?<!字符串)" 零宽负向后行断言,即
//^((?!cn).)+$ 匹配出不带cn的
www.png.com.cn //不匹配
www.png.com //匹配
www.png //不匹配
www.png.cn //不匹配
nd.com //匹配
cn.sd //不匹配
csadan.cm //匹配
cn //不匹配
cm.cn //不匹配
c.n //匹配
5、字符域
用[]表示一个区域的字符,如[0-9]、[a-z]、[3-9]、[C-N]、[0596mz]
- [0-9],所有数字
- [a-z],所有小写字母
- [A-Z],所有大写字母
- [\u4e00-\u9fa5],所有中文字符
6、分组
用()表示一个一个整体
//匹配出"m8m8"
Pattern pattern2 = Pattern.compile("^(m8)+", Pattern.CASE_INSENSITIVE);
String line2 = "m8m8pl233";
7、通配符
- \d,数字相当于[0-9]
- \D,非数字的其他字符,相当于[^0-9]
- \w,字母、数字、下划线
- \W,除字母数字下划线之外的字符
- .,一个英文圆点,表示除回车符\r和换行符\n之外的所有字符
- \s,单个的空格符、tab符\t、回车符\r、换行符\n
- \S,除了\s中字符外的其他字符
- \t,tab符
- \r,回车符,一般配合换行符\n使用,键盘上的"Enter"键即表示\r\n组合
//匹配出"=u+30"
Pattern pattern2 = Pattern.compile("^(\\D+)\\d+", Pattern.CASE_INSENSITIVE);
String line2 = "=u+30-h-89m8pl233";
//匹配出"u30_h89m=+(.)"
Pattern pattern2 = Pattern.compile("^(\\w+)\\W+");
String line2 = "u30_h89m=+(.)_8pl233";
//匹配出"u30_h89m=+(.)_8pl"
Pattern pattern2 = Pattern.compile("^.+");
String line2 = "u30_h89m=+(.)_8pl\r2332222\n2222";
Pattern pattern2 = Pattern.compile("[a-z]\\s+(\\d)");
String line2 = "u30_h\t89m=+(.)_8pl\r\n23m 32222v\n9222";
/**
h 8
l
2
m 3
v
9
*/
8、或"|"
//最新手机号匹配,首位1,第二位3和8时第三位0-9,第二位4时0或1或4-9,第二位5和9时非4,第二位6时2567,第二位7时0-8,后八位没有限制
Pattern pattern2 = Pattern.compile("^1([38][0-9]|4([01]|[4-9])|[59][^4]|6[2567]|7[0-8])([0-9]{8})");
String line2 = "15020121219";
二、Pattern类和Macher类
1、Pattern中的模式修正
- Pattern.CASE_INSENSITIVE,不区分大小写
- Pattern.COMMENTS,允许空白和注释
- Pattern.MULTILINE,启用多行模式
private static final Pattern PATTERN = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)", Pattern.CASE_INSENSITIVE);
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
String result ="---";
if(matcher.find()){
result = matcher.group(0);
}
2、Pattern中的matches方法
//返回boolean
System.out.println(Pattern.matches(".*[0-9]{2}", "99991231"));
3、String中的matches方法
//返回boolean 使用的是Pattern.matches
System.out.println("99991231".matches(".*[0-9]{2}"));
三、正则表达式引擎和优化