正则表示的概念
- 正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等工作。
- 其实正则表达式是一个非常简单而且非常实用的工具。
- 正则表达式是一个用来匹配字符串的模板。
- 在Java中定义的任何一个字符串都可以作为正则表达式使用。
- “表示字符串的字符串”
- 如果正则表达式只能匹配"abc"这样的字符串,那么正则表达式就不值得学习了
正则表达式
正则表达式有很多种匹配方法,String类下提供了直接匹配的方法:
str.matches(正则)
String regex = "abc"; String str = "abcd"; System.out.println(str.matches(regex)); |
正则表达式的符号
推荐一段代码,在测试下面的方法的时候,只需要修改函数中正则表达式的内容即可,运行时可多次试验。
import java.util.Scanner;
public class 练习 {
public static void main(String[] args) {
while(true) {
System.out.println(method());
}
}
private static String input() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的字符:");
String str = sc.nextLine();
return str;
}
public static boolean method() {
String str = input();
String regex = "[abc]{4,6}";
return str.matches(regex);
}
}
(1)预定义字符类
. | 任何字符(与行结束符可能匹配也可能不匹配) 想要匹配这个点的时候需要加上转义“\\.” |
\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")); |
(2)Greedy 数量词
X? | X,一次或一次也没有 |
X* | X,零次或多次,这里的多次指所有的字符个数都可以多次出现,不像之前的在true的情况下也是只有一次。比如[abc]? aaabbbccbbb也是返回true的 |
X+ | X,一次或多次 |
X{n} | X,恰好n次:这里是由前面X的元素组成只要是由n位就行,不要求哪个一定要出现n次 |
X{n,} | X,至少n次:同样不考虑X中元素出现几次,只要是n位往上就行 |
X{n,m} | X,至少n次,但是不超过m次:同样不考虑出现几次,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,}") ); |
(3)范围表示
[abc] | 只有abc其中之一才可以 注意这里只能验证一个字符。如果输入ab或者bc等都会返回错误 |
[^abc] | 只要不是abc其中之一就可以 |
[a-zA-Z] | 在a到c或者A到C的范围内都可以包括a、c,A、C。这里的范围是任意的,是按照ASCII码值进行范围的界定,而且一个中括号内可以划定多个范围 |
[a-d[m-p]] | 这其实和上面的那个相同,都是两个范围的并集内进行划定 |
[a-z&&[def]] | 这里后面的括号可加可不加,但是还是加上比较清晰一点,表示并集,比如1-7&&5-9,那么只有5,6,7可以返回true |
[a-z&&[^bc]] | 还是交集,不过后面的范围变成了一个补集 |
[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,}")); |
4、单词边界 \b
\b 表示单词边界,除了\w中的字符外的其他字符都可以作为单词边界。
例如:"hi.*" 和 "high" 匹配
"ahi.*" 和 "ahigh" 匹配
"a.hi.*"和 "axhigh" 匹配
但 "a.\\bhi.*" 和 "axhigh" 不匹配,为什么?
因为\b表示单词的边界,空格把 a 和high分成了两个单词。也就是说 high是另一个单词的开始处在边界上,所以就匹配。而x不会把a和high分成两个单词。
思考 "a.\\bhi.*" 和 "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 |
5、正则表达式的分组
如果想匹配3个数字,正则表达式可以用如下写法: \d{3}。
但是:在实际应用中,往往需要重复多个字符,例如想重复ab两个字符,使用以下代码就不合适了[ab]{3}。 如何解决这个问题?
使用分组:在正则表达式中,使用()来表示分组。(ab){3}。这里正确匹配就是ababab
所谓分组就是使用小括号将一些项包括起来,使其成为独立的逻辑域,那么就可以像处理一个独立单元一样去处理小括号的内容。
这种分组叫做捕获组,可以做反向引用。
什么是反向引用?
反向引用指的就是使用 \组号 来表示引用前面哪一组中的内容。
示例代码
String regex = "(a)(b)(c)" ;// 分3组 分别为:(a)、(b)、(c) 组号为 1,2,3 System.out.println("abc".matches(regex)); |
示例代码2
示例代码3
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); } |
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+");//这里的\\1是转义,代表的是\1,SOH文头字符。 for(String s : arr){ System.out.println(s); } } |
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");//正则表达式只能在replaceAll中使用 System.out.println(str5); } } |
案例1:替换电话号码为 ******
String str = "联系我:18610637606联系我:13510637606联系我:13810637606联系我:18610637606联系我:17610637606联系我:18910637606";
public class Demo14_替换电话 {
public static void main(String[] args) {
String str = "联系我:18610637606联系我:13510637606联系我:13810637606联系我:18610637606联系我:17610637606联系我:18910637606";
String regex = "(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}"; str = str.replaceAll(regex,"*****"); System.out.println(str); } } |
2 还原口吃说话
String str = “我我我我我我要要要要要要要要要要努努努努努努努力力力力力力”;
// 还原成 “我要努力”
public class Demo15_替换功能_还原口吃说话 {
public static void main(String[] args) {
String str = "我我我要要要要要努努努努努努努力力力力力力"; // "我要努力" String regex = "(.)\\1+"; //str = str.replaceAll(regex, "(.)"); str = str.replaceAll(regex, "$1"); // $1在正则表达式外取某组中的内容 System.out.println(str); } } |
9、正则的获取功能(查找子串)
查找子串同样要由 Pattern 和 Matcher 来完成
Matcher 下的常用方法
find() 是否包含匹配正则的子串
group() 取出子串
start() 符合条件子串的开始位置
end() 符合条件子串的结束位置
示例代码
public class Demo16_查找子串 {
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()); } } } |