一、正则表达式
1.1正则表达式的概念
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等工作。
正则表达式是一个用来匹配字符串的模板。
在java中定义的任何一个字符串都可以作为正则表达式使用。
如果正则表达式只能匹配"abc"这样的字符串,那么正则表达式就不值得学习了。
1.2判断字符串是否匹配正则表达式的方式
-
方式一
1 将一个字符串编译成Pattern对象。
Pattern p = Pattern.compile(正则表达式);
2 使用Pattern对象创建Matcher对象
Matcher m = p.matcher(要匹配的字符串);
3 调用Matcher类的matches()方法
m.matches() 返回true表示匹配,返回false表示不匹配。
示例代码
String regex = "abc"; //正则表达式
Pattern p = Pattern.compile(regex); //把regex这个字符串当成正则
String str = "aaa"; //字符串 要判断str这个字符串是否匹配 regex这正则
Matcher m = p.matcher(str);
System.out.println(m.matches());
-
方式二
使用Pattern下的静态方法 matches()。
Pattern.matches(正则,字符串)
示例代码
String regex = "abc";
String str = "abc";
System.out.println(Pattern.matches(regex, str));
-
方式三 jdk5开始提供的功能
String类下提供了直接匹配的方法。
str.matches(正则)
1.3正则表达式的符号
-
预定义字符类
. | 任何字符(与行结束符可能匹配也可能不匹配) |
---|---|
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
示例代码
System.out.println("a".matches(".")); System.out.println("1".matches("\\d")); System.out.println("%".matches("\\D")); System.out.println("\r".matches("\\s")); System.out.println("^".matches("\\S")); System.out.println("a".matches("\\w"));
-
Greedy 数量词
X? | X,一次或一次也没有 |
---|---|
X* | X,零次到多次 |
X+ | X,一次或多次 |
X{n} | X,恰好n次 |
X{n,} | X,至少n次 |
X{n,m} | X,至少n次,但是不超过m次 |
示例代码
System.out.println( "a".matches(".") ); System.out.println( "a".matches("a") ); System.out.println("a".matches("a?") ); System.out.println( "aaa".matches("a*") ); System.out.println( "".matches("a+") ); System.out.println( "aaaaa".matches("a{5}") ); System.out.println( "aaaaaaaaa".matches("a{5,8}") ); System.out.println( "aaa".matches("a{5,}") ); System.out.println( "aaaaab".matches("a{5,}") );
-
范围表示
[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 |
示例代码
System.out.println( "a".matches("[a]") ); System.out.println( "aa".matches("[a]+") ); System.out.println( "abc".matches("[abc]{3,}") ); System.out.println( "abc".matches("[abc]+") ); System.out.println( "dshfshfu1".matches("[^abc]+") ); System.out.println( "abcdsaA".matches("[a-z]{5,}") ); System.out.println( "abcdsaA12".matches("[a-zA-Z]{5,}") ); System.out.println( "abcdsaA12".matches("[a-zA-Z0-9]{5,}") ); System.out.println( "abdxyz".matches("[a-c[x-z]]+")); System.out.println( "bcbcbc".matches("[a-z&&[b-c]]{5,}")); System.out.println( "tretrt".matches("[a-z&&[^b-c]]{5,}"));
1.4单词边界 \b
\b 表示单词边界,除了\w中的字符外的其他字符都可以作为单词边界。
例如:"hi.*" 和 "high" 匹配
"ahi.*" 和 "ahigh" 匹配 "a.hi.*"和 "axhigh" 匹配 但 "a.\\bhi.*" 和 "axhigh" 不匹配 为什么?
因为\b表示单词的边界 空格把 a 和high分成了两个单词 也就是说 high是另一个单词的开始处在边界上,所以就匹配。而x不会把a和high分成两个单词。
示例代码
String regex = "a.\\bhi.*"; // \b不会占位 所以要配置 . 除了\w中的字符外的其他字符都可以作为单词边界 System.out.println("axhigh".matches(regex)); //false System.out.println("a high".matches(regex)); //true System.out.println("a#high".matches(regex)); //true System.out.println("a$high".matches(regex)); //true System.out.println("a_high".matches(regex)); //false System.out.println("a9high".matches(regex)); //false
1.5正则表达式分组
如果想匹配3个数字,正则表达式可以用如下写法: \d{3}。
但是:在实际应用中,往往需要重复多个字符,例如想重复ab两个字符,使用以下代码就不合适了[ab]{3}。
使用分组解决上述问题。
分组
使用分组:在正则表达式中,使用()来表示分组。(ab){3}。
所谓分组就是使用小括号将一些项包括起来,使其成为独立的逻辑域,那么就可以像处理一个独立单元一样去处理小括号的内容。
这种分组叫做捕获组,可以做反向引用。
注意: 反向引用指的就是使用\\组号 来表示引用前面哪一组中的内容。
示例代码1
String regex = "(a)(b)(c)" ;// 分3组 分别为:(a)、(b)、(c) 组号为 1,2,3
示例代码2
String regex = "((a)(b(c)))"; //如何确定分组 //查看向左的括号即可 //第一组:((a)(b(c))) //第二组:(a) //第三组:(b(c)) //第四组:(c)
示例代码3
String regex = "((a)(b(c)))\\3+"; //第一组:((a)(b(c))) //第二组:(a) //第三组:(b(c)) //第四组:(c) System.out.println("abcbcbc".matches(regex));
1.6正则的匹配功能
需求:校验QQ号,要求:必须是5~15位数字,0不能开头。
-
没有正则表达式之前
public static void checkQQ(String qq){ int len = qq.length(); if(len>=5 && len <=15){ if(!qq.startsWith("0")){ try{ long l = Long.parseLong(qq); System.out.println("qq:"+l); } catch (NumberFormatException e){ System.out.println("出现非法字符"); } } else System.out.println("不可以0开头"); } else System.out.println("QQ号长度错误"); }
-
使用正则表达式
public static void checkQQ2(){ String qq = "12345"; String reg = "[1-9][0-9]{4,14}"; boolean b = qq.matches(reg); System.out.println("b="+b); }
1.7正则的切割功能
需求1:根据空格对一段字符串进行切割。
public static void testSplit(){ String str = "-1 99 4 23"; String[] arr = str.split(" +"); for(String s : arr){ System.out.println(s); } }
需求2:根据重叠词进行切割
public static void testSplit2(){ String str = "adqqfgkkkhjppppcat"; String[] arr = str.split("(.)\\1+"); for(String s : arr){ System.out.println(s); } }
1.8正则的替换功能
String类的replaceAll方法
示例代码
public class Demo13_替换功能 { public static void main(String[] args) { String str = "www.baidu.com"; String str2 = str.replace("w", "x"); System.out.println(str2); String str3 = str.replaceAll("w","x"); System.out.println(str3); String str4 = str.replaceAll(".", "x"); System.out.println(str4); String str5 = str.replaceAll("[a-z]", "x"); System.out.println(str5); } }
需求1:替换电话号码为 ****** String str = "联系我:18610637606联系我:13510637606联系我:13810637606联系我:18610637606联系我:17610637606联系我:18910637606";
示例代码
String str = "联系我:18610637606联系我:13510637606联系我:13810637606联系我:18610637606联系我:17610637606联系我:18910637606"; String reg = "(\\d{3})(\\d{4})(\\d{4})"; String x = str.replaceAll(reg, "$1****$3"); System.out.println(x);
需求2: String str = “我我我我我我要要要要要要要要要要努努努努努努努力力力力力力”; // 还原成 “我要努力”
示例代码
public static void main(String[] args) { String str = "我我我要要要要放放放放放放假假假假假假"; // "我要放假" String regex = "(.)\\1+"; str = str.replaceAll(regex, "$1"); // $1在正则表达式外取某组中的内容 System.out.println(str); }
1.9正则的获取功能(查找子串)
查找子串同样要由 Pattern 和 Matcher 来完成。
Matcher 下的常用方法 :
-
find() 是否包含匹配正则的子串
-
group() 取出子串
需求:查找字符串中所有四个长度的子串
示例代码
public class Demo1{ public static void main(String[] args) { String str = "aaa abcd axss xssdf"; // 找到所有4个长度的子串 String regex = "\\b[a-zA-Z]{4}\\b"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); while(m.find()){ System.out.println(m.group()); } } }