# 正则表达式
一、通配符
- 第一种:\d 匹配一个数字字符,即0-9中的任意一个。
- 第二种:\D 匹配一个非数字字符。
- 第三种:\w 匹配任意一个数字、字母和下划线。
- 第四种:\W 匹配所有\w不匹配的字符。
- 第五种:\s 匹配空白字符,包括空格、制表符、换页符。
- 第六种:\S 匹配所有\s不匹配的字符。
- 第七种:. 匹配除换行符\n之外的所有字符,仅能匹配一个字符。
- 第八种:\b 匹配空白字符,包括空格、制表符等,字符串的开头末尾也算是空白字符。
- 第八种:\B 匹配非\b的字符。
public static void main(String[] args) {
String str = "aabbccdd66ee88ff";
String replaceStr = str.replaceAll("\\d", "*");
System.out.println(replaceStr);
}
二、自定义通配符
- 使用一对[]创建自定义通配符。
- 自定义通配符括号内的范围指的是匹配任意一个字符。
- 把要匹配的字符写在[]中,如[abcd]表示匹配abcd任意一个字符。
- 匹配字符可以是一组或几组,如[a-d] 或[a-dy-z] 或[0-9a-z]
- []中的脱字符表示匹配除了该字符外的所有字符,如[abcd] 表示匹配除了abcd以外的任一字符。
replaceStr = str.replaceAll("[^abcd]", "*");
三、特殊字符失效区
-
\Q定义特殊字符失效区的开头。
-
\E定义特殊字符失效区的结尾。
String str2 = "a..[a]..aabb";
//在特殊字符失效区中. []就不是特殊字符,而是代表普通字符.和[]
String replaceStr2 = str2.replaceAll("\\Q..[a]..\\E", "*");
四、字符出现的次数
- 第一种:{n} 字符连续出现n次,如"\d{3}"表示任意数字字符连续出现3次。
- 第二种:{n,m} 字符至少连续出现n次,最多出现m次,如"\d{3,9}"表示任意数字字符至少连续出现3次,最多出现9次。
- 第三种:{n,} 字符至少连续出现n次,最多不限。
- 第四种:? 出现0次或1次,相当于{0,1}。
- 第五种:* 出现0次或多次,相当于{0,}。
- 第五种:+ 出现1次或多次,相当于{1,}。
- ()表示整体。
- |表示或者。
五、贪婪模式和非贪婪模式
- 正则表达式默认是贪婪模式,尽可能匹配多的字符。
String str3 = "dxxxxxdxxxd";
String replaceStr3 = str.replaceAll("d.+" , "*");
//结果是*,默认是贪婪模式
- 非贪婪模式,尽可能匹配少的字符。
String str3 = "dxxxxxdxxxd";
String replaceStr3 = str3.replaceAll("d.+?" , "*");
//结果是*xxxx*xxd,非加上问号贪婪模式
- 贪婪模式和非贪婪模式都要以匹配到字符为原则。
六、定位符
- 脱字符表示字符串的开头,只能放在字符串的开头。
String str4 = "aaayyyaaayyyaaayyy";
String replaceStr4 = str4.replaceAll("^aaa" , "*");
- $表示只匹配字符串的结尾,只能放在字符串的结尾。
String str4 = "aaayyyaaayyyaaa";
String replaceStr4 = str4.replaceAll("aaa$" , "*");
- 匹配开头或者结尾的字符串,使用或者|
String str4 = "aaayyyaaayyyaaa";
String replaceStr4 = str4.replaceAll("^aaa|aaa$" , "*");
- \b的使用
String str5 = "win a windows";
String replaceStr5 = str5.replaceAll("win\\b" , "lose");
//结果是lose a windows \\b表示空白字符,是指空白字符、制表符等
七、正反向预搜索
- 正向预搜索,在正则表达式右边加上(?=你设定的值或正则表达式)
- 在正则表达式右边加上(?!你设定的值或正则表达式)
String str6 = "windowsNT windows7 windows8 windows10";
String replaceStr6 = str6.replaceAll("windows(?=NT)" , "*");
//结果是*NT windows7 windows8 windows10 匹配windows右边是NT的字符串
replaceStr6 = str6.replaceAll("windows(?=\\d)" , "*");
//结果是windowsNT *7 *8 *10 匹配windows右边是数字的字符串
replaceStr6 = str6.replaceAll("windows(?!\\d)" , "*");
//结果是*NT windows7 windows8 windows10 匹配windows右边不是数字的字符串
- 反向预搜索,在正则表达式的左边加上(?<=你设定的值或正则表达式)
- 在正则表达式左边加上(?<!你设定的值或正则表达式)
String str6 = "AwindowsNT Bwindows7 Cwindows8 Dwindows10";
String replaceStr6 = str6.replaceAll("(?<=A)windows" , "*");
//结果是A*NT Bwindows7 Cwindows8 Dwindows10
replaceStr6 = str6.replaceAll("(?<!A)windows" , "*");
//结果是AwindowsNT B*7 C*8 D*10
<八、反向引用>
1、使用小括号对字符进行编号,从左到右,第一个括号编号是1,依次类推
String str7 = "ababcffceeee";
String replaceStr7 = str7.replaceAll("(.)(.)\\2\\1" , "*");
//结果是abab** 其中\\2表示与第二个编号字符相同,\\1表示与第一个编号字符相同,标号就是小括号从左到右读取,第一个括号编号是1,依次类推
String str7 = "ababcffceeee";
replaceStr7 = str7.replaceAll("(.)\\1{3,}" , "*");
//结果是ababcffc*
2、括号中的?:表示当前不被编号,如(?:ab)(b)\1 表示(ab)不被编号,编号为1的是(b)
3、对小括号中的字符进行编号,如(?ab)©\k 表示对(ab)自定义编号为firstNum,然后后面可以使用\k<编号名称>引用,如\k
九、Pattern类
1、得到Pattern类,使用Pattern.compile(“正则表达式”)
2、得到正则表达式pattern.pattern();
3、分割字符串 pattern.split(“要分割的字符串”);
4、分割成几个部分pattern.split(“要分割的字符串”,分割几部分数)
5、验证是否匹配正则表达式Pattern.matches(“正则表达式”,“字符串”)
6、返回字符失效区字符串Pattern.quote(“字符串”)
Pattern pattern = Pattern.compile("\\d");
String regex = pattern.pattern(); //结果是\d 得到正则表达式
String strTest = "addd2aaa3fff5hdd6yj7";
String[] split = pattern.split(strTest); //分割字符串
String[] split2 = pattern.split(strTest ,2); //分割字符串 ,只分割两个部分
Boolean boo = Pattern.matches("\\d[abc]" , "3a"); //检测是否匹配
String quote = Pattern.quote("\\d[abc]"); //返回一个\Qd[abc]\E 自动加上字符失效区返回字符串
十、匹配模式和标志
1、正则表达式忽略大小写,需要在正则表达式后面设置
//忽略正则表达式的大小写,只不区分英文字母大小写
Pattern.compile("\\d[abc]" , Pattern.CASE_INSENSITIVE);
2、正则表达式忽略所有字母的小大写
//所有都不区分大小写
Pattern.compile("\\d[abc]" , Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
3、正则表达式忽略大小写
String str8 = "xyz1Aubhhs2afff3c";
//忽略英文的大小写,使用?i
String s = str.replaceAll("(?i)\\d[abc]", "*");
//忽略所有的大小写,使用?iu
String s2 = str.replaceAll("(?iu)\\d[abc]", "*");
4、匹配模式是指正则表达式的工作方式。
5、匹配模式的开始标志是(?) ,结束标志是(?-)
6、常用的匹配模式:
CASE_INSENSITIVE (?i)匹配过程中忽略大小写
UNICODE_CASE (?u)忽略大小写至整个unicode,必须先设置CASE_INSENSITIVE,一般使用方式为(?iu)
MULTILINE (?m)匹配过程中把换行符\n也堪称一行的结尾
DOTALL (?s)允许匹配换行符
COMMENTS (?x)忽略正则表达式中的空白字符
十一、Macher类
1、Matcher类需要使用Pattern的matcher()方法来创建
String str = "1a";
//创建Mathcer对象
Pattern p = Pattern.compile("\\d\\w");
Matcher m = p.matcher(str);
2、pattern()得到正则表达式:m.pattern()
3、判断字符串整体是否匹配:m.matches()
4、判断字符串开头是否匹配:m.lookingAt()
5、看是否找到匹配的字符串:m.find() 如果是m.find(9)从索引9开始找
6、输出找到的字符字符串:m.group()
if(m.find()){ //找到字符串
System.out.println(m.group());//匹配匹配到的字符串
}
while (m.find()){
System.out.println(m.group());//输出匹配到的字符串
System.out.println(m.start());//输出匹配到字符串的起始索引
System.out.println(m.end());//输出匹配到字符串的结束索引
}
7、获取匹配到字符串的起始位置:m.start()
8、获取匹配到字符串的结束位置:m.end()
9、匹配之后重新回到起点位置:m.reset()
10、m.group(2)表示匹配匹配项中的第二组中的内容,一个括号表示一个组,比如正则表达式是(\d)(\w) ,第一个组是(\d),第二个组是(\w) ,如果是m.group(0)表示匹配这个组中的所有内容,即是(\d)(\w)
11、m.start(2)表示真个匹配项中组2的起始位置
12、正则表达式中组的数量:m.groupCount()
13、把匹配到的所有对象都封装到一个MatchResult中:m.toMatchResult()
一般使用方式是:
while (m.find()){
Matcher mr = (Matcher) m.toMatchResult();
}
14、替换第一个匹配到的字符串
String str2 = "asdd11ghh";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.replaceFirst("*");//把匹配到的第一个字符创替换成*
15、替换所有匹配到的字符串
String str2 = "asdd11ghh";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.replaceAll("*");//把匹配到的所有字符创替换成*
16、在执行替换方法后,在执行find方法是找不到匹配到的字符串,因为游标在字符串的最后面,如果需要重新匹配需要加reset方法。
String str2 = "asdd11ghh";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.replaceAll("*");//把匹配到的所有字符创替换成*
System.out.println(m2.find());//结果是false,因为匹配的游标已经在字符创的最右边,调用find()找不到能匹配到的数据
17、m.appendReplacement()方法,把匹配项匹配的内容替换成目标字符串后,写到StringBuffer中
String str2 = "ad11ghh";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
StringBuffer buff = new StringBuffer("xxx");
if (m2.find()) {
m2.appendReplacement(buff , "*");
}
System.out.println(buff);//输出xxxad* 表示把字符串str2中的第一个1匹配到,并且把1替换成*,把当前下标之前的数据追加到buff
18、appendTail方法
String str2 = "ad1gh1hkkk";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
StringBuffer buff = new StringBuffer("xxx");
while (m2.find()) {
m2.appendReplacement(buff , "*");
}
m2.appendTail(buff);//把游标最后匹配不到的追加在buff
System.out.println(buff);
19、搜索范围:region(起始下标,结束下标) 如m.resion(4,9)只搜索4-9的索引
String str2 = "ad1gh1hkkk";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.region(2,5);
while (m2.find()) {
System.out.println(m2.group());
}
20、region后如果调用reset方法或解除局部索引范围,region对replaceFirst和replaceAll方法没有影响,还是会全部替换。
21、如果find(5)设置了索引,就从find的索引位置开始找,不从region的范围开始找
String str2 = "1ad3gh1hkkk";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.region(2,5);
m2.find(0);
System.out.println(m2.group());//应该是从字符串的第一个开始找,输出的是1
22、Matcher中的replaceAll()方法,replaceFirst()方法、和find(参数)方法都内置reset方法
23、更换正则表达式:m.usePattern()
String str2 = "1ad3gh1hkkk";
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher(str2);
m2.usePattern(Pattern.compile("[abcd]")); //更换正则表达式