一. 正则引出

1
2
3
4
5
6
7
8
9
package cn.ngp.demo;
import java.util.Arrays;
import java.util.regex.Pattern;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "123";
System.out.println(str.matches("\\d+"));
}
}

     如以上代码,在判断字符串是否为数字的时候,如果用if语句判断,那么可能要8行左右才能做到,而用正则表达式,只需要一行简单的操作就实现了,而其中出现的 \\d+ 就是正则表达式。
     正则是从JDK1.4的时候正式引入到 java中的工具类,所有正则支持的类都定义在 java.util.regex包里面。在JDK1.4之前,如果要想使用正则,则需要单独下载一个正则表达式的开发包后才可以使用。(正则表达式的原理: 离散数学)
     在 java.util.regex包里面定义了两个主要的类:

  • Pattern类: 此类对象如果想要取得必须使用compile()方法,方法的功能是编译正则。
  • Matcher类: 通过Pattern类取得。

(正则里面最重要的不是方法名称,而是标记,例如 \\d+

二. 正则 标记(核心、核心、核心)

     所有的正则可以使用的标记都在 java.util.regex.Pattern类里面定义。
1、单个字符(数量: 1)

  • 字符 : 表示由以为字符所组成;
  • \\ : 表示转义字符  "  \  " ;
  • \t : 表示一个  " \t "  符号;
  • \n : 匹配换行 ( " \n "  符号)

2、字符集(数量:1):

  • [abc] : 表示可能是字符a、或者是字符b、或者是字符c中的任意一位;
  • [^abc] : 表示不是a、b、c中的任意一位;
  • [a-z] : 所有的小写字母;
  • [A-Z] : 所有的大写字母;
  • [a-zA-Z] : 表示任意的一位字母,不区分大小写;
  • [0-9] : 表示任意的一位数字。

3、简化的字符集表达式(数量:1):

  • . : 表示任意的一位字符;
  • \d : 等价于 " [0-9] " ,属于简化写法;
  • \D : 等价于 " \[^0-9] " ,属于简化写法;
  • \s : 表示任意的空白字符,例如 " - \t " 、 " - \n " ;
  • \S : 表示任意的非空白字符;
  • \w : 等价于 " [a-zA-Z_0-9] " ,表示由任意的字母、数字、_所组成;
  • \W : 等价于 " [^a-zA-Z_0-9] " ,表示不是由任意的字母、数字、_所组成;

4、边界匹配(不要在Java中使用,在JavaScript中使用) :

  • ^ : 正则的开始;
  • $ : 正则的结束;

5、数量表达 :

  • 正则? : 表示此- 正则可以出现0次或1次;
  • 正则+ : 表示此- 正则可以出现1此或1次以上;
  • 正则* : 表示此- 正则可以出现0次、1次或多次;
  • 正则{n} : 此- 正则正好出现n次;
  • 正则{n,} : 表示此- 正则出现n次以上(包含n);
  • 正则{n,m} : 表示此- 正则出现n~m次(包含n和m);

6、逻辑运算 :

  • 正则1 正则2 : 正则1判断完成之后判断正则2 (相当于&的操作);
  • 正则1 | 正则2 : 正则1或者是正则2有一组满足即可;
  • (正则) : 将多个正则作为1组**(当成一个整体)**,可以为这一组单独设置出现的次数。

三. String类对正则的支持(重点)

     在JDK1.4之后,由于正则的引入,所以String类里面也相应的增加了心的操作方法支持。
1
     这三组方法在工作中用得特别多。
     给出的几个方法里面对于替换和拆分实际上难度不高,最关键就是正则匹配,在验证上使用的特别多。

范例: 实现字符串拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.ngp.demo;
import java.util.Arrays;
import java.util.regex.Pattern;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "I2389have283a239dream39";
String regex = "\\d+"; //此处编写正则
String result [] = str.split(regex);
for(int x = 0 ; x < result.length ; x ++) {
System.out.println(result[x]);//按任意长度的数字进行拆分
}
}
}

     所有正则之中最应该引起我们兴奋的事情是因为可以使用它进行验证。(str.matches)

范例: 验证一个字符串是否是数字,如果是则将其变为double型
数字可能是整数(10),也可能是小数(10.2)

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.ngp.demo;
import java.util.Arrays;
import java.util.regex.Pattern;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "10";
String regex = "\\d+(\\.\\d+)?";
System.out.println(str.matches(regex));
if(str.matches(regex)) {
System.out.println(Double.parseDouble(str));
}
}
}

范例: 判断给定的字符串是否是一个IP地址(IPV4)
IP地址:192.168.1.1 每一个段最大是三个长度(1~3个长度都可以)

1
2
3
4
5
6
7
8
9
10
11
package cn.ngp.demo;
import java.util.Arrays;
import java.util.regex.Pattern;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "192.168.1.1";
// String regex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}";
String regex = "(\\d{1,3}\\.){3}\\d{1,3}"; // 优化
System.out.println(str.matches(regex));
}
}

范例: 给定一个字符串,判断是否是日期格式,如果是则将其转换为Date型数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.ngp.demo;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "2019-03-09";
String regex = "\\d{4}-\\d{2}-\\d{2}";
System.out.println(str.matches(regex));
if(str.matches(regex)) {
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(str);
System.out.println(date);
}
}
}

范例: 判断电话号码,一般要编写电话号码以下几种格式都是满足的:

  • 格式一: 51283346 //一般长度是7~8位的数字是电话号码
    • 验证格式: \\d{7,8}
  • 格式二: 010-51283346 //区号一般是3~4位,而且区号的电话之间的 “-” 只有在出现区号时出现
    • 验证格式: (\\d{3,4}-)?\\d{7,8}
  • 格式三: (010)-51283346 //两边括号得同时存在,所以↓
    • 验证格式: ((\\d{3,4}-)|(\\(\\d{3,4}\\)-))?\\d{7,8}
1
2
3
4
5
6
7
8
package cn.ngp.demo;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "(010)-51283346";
String regex = "((\\d{3,4}-)|(\\(\\d{3,4}\\)-))?\\d{7,8}";
System.out.println(str.matches(regex));
}
}

范例: 验证email地址
要求格式一: (最简单的拆分)
2

  • 验证格式: \\w+@\\w+\\.\\w+

要求格式二: (比较有难度更符合实际的拆分)
     用户名要求由字母、数字、_.、组成,其中必须以字母开头,可以以字母和数字结尾,用户名长度不超过30,最后的根域名只能够是 .com、.cn、.net、com.cnnet.cn 、edu 、gov 、org 。
3

  • 验证格式: [a-zA-Z][a-zA-Z0-9_\\.]{0,28}[a-zA-Z0-9]@\\w+\\.(com|cn|net|com.cn|net.cn|edu|gov|org)
1
2
3
4
5
6
7
8
package cn.ngp.demo;
public class TestDemo {
public static void main(String[] args) throws Exception {
String str = "hello.nihao123_123@ngp.cn";
String regex = "[a-zA-Z][a-zA-Z0-9_\\.]{0,28}[a-zA-Z0-9]@\\w+\\.(com|cn|net|com.cn|net.cn|edu|gov|org)";
System.out.println(str.matches(regex));
}
}

     以上是几个典型的数据检验操作,而在以后会接触到类似检验的时候,一定可以要求自己直接写出。

四. java.util.regex包支持(理解)

     在大多数情况下使用正则的时候采用String类完成,但是正则最原始的开发包是java.util.regex,这个包里面也提供有两个类。
范例: Pattern类

参考

来自: 阿里云大学(笔记) → 零基础学Java10系列三:Java高级编程