从零开始学Java-正则表达式:校验字符串

175 阅读6分钟

什么是正则表达式呢?我们先来看个案例:

需求:假如现在要求校验一个qq号码是否正确。 规则:6位及20位之内,0不能在开头,必须全部是数字。

我们先用以前的写法:

String qq = "123456789";
System.out.println(checkQQ(qq));

// 以前的写法
public static boolean checkQQ(String qq) {
    // 规则:6到20以内,0不能开头,必须全部是数字
    int len = qq.length();
    if (len < 6 || len > 20) {
        return false;
    }
    // 0不能在开头
    if (qq.startsWith("0")) {
        return false;
    }
    // 必须全部是数字
    for (int i = 0; i < qq.length(); i++) {
        char c = qq.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}

哇,这是不是好麻烦呀?那我们用正则表达式看一下:

System.out.println(qq.matches("[1-9]\\d{5,19}"));

一行代码直接搞定了,怎么样,是不是很方便呀!下面我们一起来学习一下吧:

正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性。

  • 正则表达式作用
  1. 校验字符串是否满足规则
  2. 在一段文本中查找满足要求的内容

image.png

我们来实操一下吧:

  • 只能是a b c (只能匹配一个字符)
System.out.println("a".matches( "[abc]"));// true
System.out.println("z".matches("[abc]"));// false
System.out.println("ab".matches("[abc]"));// false
  • 不能出现a b c (只能匹配一个字符)
System.out.println("a".matches( "[^abc]"));// false
System.out.println("z".matches( "[^abc]"));// true
System.out.println("zz".matches( "[^abc]"));// false
System.out.println("zz".matches( "[^abc][^abc]"));// true
  • a到z A到Z(包括头尾的范围) (只能匹配一个字符)
System.out.println("a".matches( "[a-zA-Z]"));//true
System.out.println("z".matches( "[a-zA-Z]"));//true
System.out.println("aa".matches( "[a-zA-Z]"));//false
System.out.println("zz".matches( "[a-zA-Z]"));//false
System.out.println("0".matches( "[a-zA-Z]"));//false
System.out.println("0".matches( "[a-zA-Z0-9]"));//true
  • [a-d[m-p]] a到d,或m到p (只能匹配一个字符)
System.out.println("a".matches("[a-d[m-p]]"));//true
System.out.println("d".matches("[a-d[m-p]]"));//true
System.out.println("m".matches("[a-d[m-p]]"));//true
System.out.println("p".matches("[a-d[m-p]]"));//true
System.out.println("e".matches("[a-d[m-p]]"));//false
System.out.println("0".matches("[a-d[m-p]]"));//false
  • [a-z&&[def]]a-z和def的交集。为:d,e,f (只能匹配一个字符)
System.out.println("a".matches("[a-z&[def]]"));//false
System.out.println("d".matches("[a-z&[def]]"));//true
System.out.println("0".matches("[a-z&[def]]"));//false
  • [a-z&&[^bc]]a-z和非bc的交集。(等同于[ad-z]) (只能匹配一个字符)
System.out.println("a".matches( "[a-z&&[^bc]]")); //true
System.out.println("b".matches( "[a-z&&[^bc]]")); //false
System.out.println("0".matches( "[a-z&&[^bc]]")); //false
  • [a-z&&[^m-p]] a到z和除了m到p的交集。(等同于[a-lg-z]) (只能匹配一个字符)
System.out.println("a".matches("[a-z&&[^m-p]]"));//true
System.out.println("m".matches("[a-z&&[^m-p]]"));//false
System.out.println("0".matches("[a-z&&[^m-p]]"));//false

image.png

下面我们也来实操一下预定义字符吧:

  • .表示任意一个字符
System.out.println("你".matches(".."));//false
System.out.println("你".matches("."));//true
System.out.println("你a".matches(".."));//true
  • \d只能是任意的一位数字,简单来记:两个\表示一个\
System.out.println("a".matches("\d"));// false
System.out.println("3".matches("\d"));// true
System.out.println("333".matches("\d"));// false
System.out.println("333".matches("\d\d\d"));// true
  • \w只能是一位单词字符[a-zA-z_8-9]
System.out.println("z".matches("\w"));// true
System.out.println("2".matches("\w"));// true
System.out.println("21".matches("\w"));// false
System.out.println("你".matches("\w"));//false
  • 非单词字符
System.out.println("你".matches("\W"));// true
System.out.println("w".matches("\W"));// false

以上正则只能匹配校验单个字符,想要匹配多个就想需要使用下面方法:

image.png

  • 必须是数字 字母下划线 至少 6位
System.out.println("2442fsfsf".matches("\w{6,}"));//true
System.out.println("244f".matches("\w{6,}"));//false
  • 必须是数字和字符 必须是4位
System.out.println("-----------6-------------");
System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));//true
System.out.println("23dF".matches("[\w&&[^_]]{4}"));//true
System.out.println("23_F".matches("[a-zA-Z0-9]{4}"));//false
System.out.println("23_F".matches("[\w&&[^_]]{4}"));//false
  • 忽略大小写字母
  1. 在匹配的时候忽略abc的大小写
String regex4="(?i)abc";
System.out.println("abc".matches(regex4));  // true
System.out.println("ABc".matches(regex4));  // true
System.out.println("aBc".matches(regex4));  // true

2. 在匹配的时候忽略bc的大小写

String regex5="a(?i)bc";
System.out.println("abc".matches(regex5));  // true
System.out.println("ABc".matches(regex5));  // false
System.out.println("aBc".matches(regex5));  // true

3. 在匹配的时候忽略b的大小写

String regex6="a((?i)b)c";
System.out.println("abc".matches(regex6));  // true
System.out.println("ABc".matches(regex6));  // false
System.out.println("aBc".matches(regex6));  // true

到这里就学完啦,我们下面来做几个案例吧:

  • 请编写正则表达式验证用户输入的手机号码是否满足要求。

验证手机号码 13112345678 131123456781

分成3部分:
第一部分:1  表示手机号码只能以1开头。
第二部分:[3-9]  表示手机号码第二位只能是3-9之间的。
第三部分:\d{9} 表示任意数字可以出现9次,也只能出现9次。
String regex1 = "1[3-9]\d{9}";
System.out.println("13112345678".matches(regex1));//true
System.out.println("131123456781".matches(regex1));//false
  • 请编写正则表达式验证用户输入的邮箱号是否满足要求。

验证座机电话号码 020-2324242 07123242434

分成3部分:
第一部分:0  表示号码只能以0开头。\d{2,3}  表示区号从第二位开始可以是任意数字,可以出现2-3次
第二部分:-  ?表示次数0次或者1次
第三部分:号码  号码第一位也不能以0开头,第二位开始可以是任意的数字,号码总长度5-10
String regex2 = "0\d{2,3}-?[1-9]\d{4,9}";
System.out.println("020-2324242".matches(regex2));//true
System.out.println("07123242434".matches(regex2));//true
  • 请编写正则表达式验证用户输入的电话号码是否满足要求

验证邮箱号码 3232323@qq.com dleieee9@pci.com.cn

分成3部分:
第一部分:@的左边    \w+    任意的字母数字下划线至少出现一次就可以了
第二部分:@   只能出现一次
第三部分:3.1 .的左边    [\w&&[^_]{2,6}]    任意的字母加数字总共出现6次,不能出现下划线
        3.2  .   \.
        3.3  .的右边    大写字母和小写字母都可以,只能出现2-3次
        (.[a-zA-Z]{2,3}){1,2}    我们可以把3.2和3.3看出一组,可以出现1次或者2次
String regex3 = "\w+@[\w&&[^_]]{2,6}(\.[a-zA-Z]{2,3}){1,2}";
System.out.println("3232323@qq.com".matches(regex3));//true
System.out.println("dleieee9@pci.com.cn".matches(regex3));//true
  • 请编写正则表达式验证用户名是否满足要求。

要求:大小写字母,数字,下划线一共4-16位

String regex1 ="\w{4,16}";
System.out.println("zhangsan".matches(regex1)); //true
System.out.println("lisi".matches(regex1)); //true
System.out.println("$123".matches(regex1)); //false
  • 请编写正则表达式验证用户身份证号码是否满足要求。

    • 简单要求:18位,前17位任意数字,最后一位可以是数字可以是大写或小写的x
    • 复杂要求:按照身份证号码的格式严格要求。
  • 简单校验

// 简单校验
String regex2 = "[1-9]\d{16}(\d|(?i)x)";
System.out.println("41080119930228457x".matches(regex2)); //true
System.out.println("01080119930228457x".matches(regex2)); //false
  • 复杂校验
//前面6位:省份,市区,派出所等信息第一位不能是8,后面5位是任意数字
//年的前半段:18 19 20
//年的后半段:任意数字出现两次
//月份:   01 ~09 10 11 .12
//日期:   81 ~ 31
//后面四位: 任意数字出现3次 最后一位可以是数字也可以是大写x或者小写x
String regex3 = "[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]";
System.out.println("41080119930228457x".matches(regex3)); //true
System.out.println("01080119930228457x".matches(regex3)); //false

下面我们来做个总结吧:

符号含义举例
0次或1次\d?
*0次或多次\d* (abc)*
+1次或多次\d+ (abc)+
{}具体次数a{7} \d{7,19}
(?i)忽略后面字符的大小写(?i)abc
a((?i)b)c只忽略b的大小写a((?i)b)c

下面我们来看一下正则表达式在字符串方法中的使用吧:

正则表达式方法

方法名说明
public string[]matches(string regex)判断字符串是否满足正则表达式的规则
public string replaceAll(string regex,string newstr)按照正则表达式的规则进行替换
public string[] split(string regex)按照正则表达式的规则切割字符串

前面我们学习了matches方法,下面我们对剩下两个来实操一下吧:

  • 先来看个例子:

    有一段字符串:小诗诗dqwefqwfqwfwg12312小丹丹dqwefqwfqwfwg12312小惠惠

    // 要求1:把字符串中三个姓名之间的字母替换为vs

    String str = "小诗诗dqwefqwfqwfwg12312小丹丹dqwefqwfqwfwg12312小惠惠";
    String result = str.replaceAll("[\w&&[^_]]+", "vs");
    System.out.println(result);
    

    image.png

    是不是全部成功替换为vs了呀!我们再来看第二个要求:

    // 要求2:把字符串中的三个姓名切割出来

    String str = "小诗诗dqwefqwfqwfwg12312小丹丹dqwefqwfqwfwg12312小惠惠";
    
    String[] arr = str.split("[\w&&[^_]]+");
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
    

    image.png

    怎么样,是不是全部把他们都给切割出来了呀!

正则表达式分组

分组:分组就是一个小括号。

image.png

正则表达式每组是有组号的,也就是序号

  1. 规则1:从1开始,连续不间断
  2. 规则2:以左括号为基准,最左边的是第一组,其次第二组,以此类推。

下面我们来实操一下吧:

  • 需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符

    • 举例: a123a b456b 17891 a123b
    String regex1 = "(.).+\1";
    System.out.println("a123a".matches(regex1));//true
    System.out.println("b456b".matches(regex1));//true
    System.out.println("17891".matches(regex1));//true
    System.out.println("a123b".matches(regex1));//false
    
  • 需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符

    • 举例: abc123abc b456b 123789123 abc123abd
    String regex2 = "(.+).+\1";
    System.out.println("abc123abc".matches(regex2));//true
    System.out.println("b456b".matches(regex2));//true
    System.out.println("123789123".matches(regex2));//true
    System.out.println("abc123abd".matches(regex2));//false
    
  • 需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致

    • 举例: aaa123aaa bbb456bbb 111789111 111789112
    String regex3 = "((.)\2*).+\1";
    System.out.println("aaa123aaa".matches(regex3));//true
    System.out.println("bbb456bbb".matches(regex3));//true
    System.out.println("111789111".matches(regex3));//true
    System.out.println("111789112".matches(regex3));//false
    

正则表达式捕获分组

后续还要继续使用本组的数据。

  1. 正则内部使用:\组号
  2. 正则外部使用:$组号

下面我们来看个案例:

需求:将字符串:我要学学编编编编程程程程程程。替换为:我要学编程

String str = "我要学学编编编编程程程程程程";
String result = str.replaceAll("(.)\1+", "$1");
System.out.println(result);

我们来看一下:

image.png

是不是就把重复的给去掉了呀!那这些正则表达式什么意思呢?我们来看一下:

// (.)  表示把重复内容的第一个字符看作第一组
// \1 表示第一字符再次出现
// +   至少一次
// $1 表示把正则表达式中第一组的内容,再拿出来用

正则表达式非捕获分组

分组之后不需要再用本组数据,仅仅是把数据括起来,不占组号。

符号含义举例
(?:正则)获取所有Java(?:8,11,17)
(?=正则)获取前面部分Java(?=8,11,17)
(?!正则)获取不是指定内容的前面部分Java(?!8,11,17)

好啦,正则表达式常用案例就学到这里啦,有什么不懂的可以在评论区评论,大家一起探讨哟,我们下期不见不散!!!

==最后非常感谢您的阅读,也希望能得到您的反馈  ==