内容学习于:edu.aliyun.com


1. 认识正则表达式

  通过之前一系列的分析可以发现,String 是一个非常万能的类型,因为String不仅仅可以支持有各种字符串的处理操作,也支持有向各个数据类型的转换功能,所以在项目的开发之中,只要是用户输入的信息基本上都用String表示。于是在向其它数据类型转换的时候,为了保证转换的正确性,往往需要对其进行一些复杂的验证处理,那么这种情况下如果只是单纯的依靠String类中的方法是非常麻烦的。
  现在假设有一个字符串要求你判断字符串是否由数字所组成,如果由数字所组成则将其变为数字进行乘法计算。

判断字符串是否全是数字代码:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "123";
        if (isNum(str)) {
            int num = Integer.parseInt(str);
            System.out.println(num * 2);
        }
    }

    public static boolean isNum(String str) {
        char data[] = str.toCharArray();
        for (char temp : data) {
            if (temp > '9' || temp < '0') {
                return false;
            }
        }
        return true;
    }

}

结果:

246

  实际上这种验证的功能是非常简单的,但是这如此简单的功能却需要开发者编写大量的程序逻辑代码,那么如果是更加复杂的验证呢?那么在这样的情况下,对于验证来讲最好的做法就是利用正则表达式来完成。

正则表达式代码:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "123";
        if (str.matches("\\d+")) {//正则表达式
            int num = Integer.parseInt(str);
            System.out.println(num * 2);
        }
    }

}

结果:

246

  正则表达式最早是从Perl语言里面发展而来的,而后在JDK1.4以前如果需要使用到正则表达式的相关定义则需要单独引入其它的*.jar文件,但是从JDK 1.4之后,正则已经默认被JDK所支持,并且提供有java.util.regex开发包,同时针对于String类进行了一些修改,使其可以有方法直接支持正则处理。
  <mark>使用正则最大的特点在于方便进行验证处理,以及方便进行复杂字符串的修改处理。</mark>

2. 常用正则表达式(背)

<mark>注:使用时若在字符串中表示,需要利用“\”转义“\”,即使用两个“\”</mark>

  如果要想进行正则的处理操作,那么就首先需要对常用的正则标记有所掌握,从JDK 1.4开始提供有java.util.regex 开发包,这个包里面提供有一个Pattern程序类,在这个程序类里面定义有所有支持的正则标记。

  a. 【数量:单个】字符匹配:

x:表示由任意字符组成
\:表示“\”
\n:匹配换行
\t:匹配制表符

  b. 【数量:单个】字符集(可以从里面任选一个字符):

[abc]:表示可能是a、b和c的任意一个
[^abc]:表示不是a、b和c的任意一个
[a-zA-Z]:表示由一个字母所组成,不区分大小写
[0-9]:表示由一个数字组成

  c. 【数量:单个】简化字符集:

.:表示任意一个字符
\d:等价于[0-9]
\D:等价于[^0-9]
\s:匹配任意的一位空格,可能是空格、换行、制表符
\S:匹配任意的非空格数据
\w:匹配字母,数字,下划线,等价于[a-zA-Z_0-9]
\W:匹配非字母,数字,下划线,等价于[a-zA-Z_0-9]

  d. 边界匹配:

^:表示边界匹配开始
$:表示边界匹配结束

  e. 数量匹配:

表达式?:该正则可以出现0次或1次
表达式*:该正则可以出现0次、1次或多次
表达式+:该正则可以出现1次或多次
表达式{n}:表示表达式的长度正好为n次
表达式{n,}:表示表达式的长度正好为n次以上
表达式{n,m}:表示表达式的长度正好为n次到m次之间

  f. 逻辑表达式:可以连接多个正则

表达式X表达式Y:表示表达式X紧跟着表达式Y
表达式X|表达式Y:表达式X或表达式Y
(表达式):为表达式设置一个整体描述,可以为整体描述设置数量单位

代码:

例子1:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "aa";//要匹配的数据
        String regex = "a";//正则规则
        System.out.println(str.matches(regex));//没法匹配数量
    }

}

结果:

false

例子2:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "a";//要匹配的数据
        String regex = "[abc]";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

true

例子3:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "2";//要匹配的数据
        String regex = "[a-zA-Z]";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

false

例子4:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "a";//要匹配的数据
        String regex = "[0-9]";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

false

例子5:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "a\n";//要匹配的数据
        String regex = "\\D\\s";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

true

例子6:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "aadad";//要匹配的数据
        String regex = "\\w+";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

true

例子7:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "aadad";//要匹配的数据
        String regex = "\\w{3,5}";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

true

3. String类对正则的支持

  在进行正则表达式大部分处理的情况下都会基于String类来完成,并且在String类里面提供有如下与正则有关的操作方法:

NO 方法名称 类型 描述
01 public boolean matches(String regex) 普通 将指定字符串进行正则判断
02 public String replaceAll(String regex,String replacement) 普通 替换全部
03 public String replaceFirst(String regex,String replacement) 普通 替换首个
04 public String[] split(String regex) 普通 正则拆分
05 public String[] split(String regex,int limit) 普通 正则拆分

实现字符串的替换(删除非字母和数字)代码:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "hlo8rk[p';{/;kfa[/'//k;j;a;f4+*+*/+4+-;";//要匹配的数据
        String regex = "[^a-zA-Z0-9]+";//正则规则
        System.out.println(str.replaceAll(regex,""));
    }
}

结果:

hlo8rkpkfakjaf44

实现字符串的拆分代码:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "gi981o89h9o0093171hdiau9o1hdo91gido9119814";//要匹配的数据
        String regex = "\\d+";//正则规则
        String result[] = str.split(regex);
        for (String temp : result) {
            System.out.printf(temp + "、");
        }
    }
}

结果:

gi、o、h、o、hdiau、o、hdo、gido、

  在正则处理的时候对于拆分与替换的操作相对容易–些,但是比较麻烦的是数据验证部分。

判断是否为小数代码:

public class JavaAPIDemo {
    public static void main(String[] args) {
        String str = "100.";//要匹配的数据
        String regex = "\\d+(\\.\\d)?\\d*";//正则规则
        System.out.println(str.matches(regex));
    }
}

结果:

false

判断是否为日期代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str = "2000-09-09";//要匹配的数据
        String regex = "\\d{4}-\\d{2}-\\d{2}";//正则规则
        if (str.matches(regex)) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse(str));
        }
    }
}

结果:

Sat Sep 09 00:00:00 CST 2000

  <mark>需要注意的是,正则表达式无法对里面的内容进行判断,只能够对格式进行判断处理。</mark>

判断电话号码代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str1 = "51283346";//要匹配的数据
        String str2 = "01051283346";//要匹配的数据
        String str3 = "(010)-51283346";//要匹配的数据
        String regex = "((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8}";//正则规则
        System.out.println("【电话格式1】:" + str1.matches(regex));
        System.out.println("【电话格式2】:" + str2.matches(regex));
        System.out.println("【电话格式3】:" + str3.matches(regex));
    }
}

结果:

【电话格式1】:true
【电话格式2】:true
【电话格式3】:true

  既然已经可以使用正则进行验证了,那么下面就可以利用其来实现一个email地址格式的验证。

  •   范例:验证email格式
  •   email的用户名可以由字母、数字、_ 所组成(不应该使用“”开头);
  •   email 的域名可以由字母、数字、_、-所组成;
  •   域名的后缀必须是: .cn、 .com、 .net、 .com.cn、 .gov;

验证email格式代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str1 = "mldnjava888@mldn.com.cn";//要匹配的数据
        String regex = "[a-zA-Z0-9]\\w+@\\w+\\.((cn)|(com)|(com\\.cn)|(gov))";//正则规则
        System.out.println("【邮箱】:" + str1.matches(regex));
    }
}

结果:

【邮箱】:true

4. java.util.regex包支持

  虽然在大部分的情况下都可以利用String类实现正则的操作,但是也有一些情况下需要使用到java.util.regex开发包中提供的正则处理类,在这个包里面一共定义有两个类: Pattern (正则表达式编译)、Matcher (匹配)。
  Pattern有两个方法:

  •   编译:public static Pattern compile(String regex)
  •   字符串拆分:public String[] split(CharSequence input)

字符串拆分代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str1 = "ada*&**IVNG*OIB(OJB(*&((YO*)*&*^%&^&(*OO:U";//要匹配的数据
        String regex = "[^a-zA-Z]+";//正则规则
        Pattern pattern = Pattern.compile(regex);//编译
        String[] result = pattern.split(str1);//拆分
        for (String t : result) {
            System.out.println(t);
        }
    }
}

结果:

ada
IVNG
OIB
OJB
YO
OO
U

  Matcher 类,实现了正则匹配的处理类,这个类的对象实例化依靠Pattern 类完成:
  Pattern 类提供的方法: public Matcher matcher(CharSequence input);

  当获取了Matcher类的对象之后就可以利用该类中的方法进行如下操作:

  •   匹配方法:public boolean matches()
  •   字符串替换:public String replaceAll(String replacement)

字符串匹配代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str1 = "6513";//要匹配的数据
        String regex = "\\d+";//正则规则
        Pattern pattern = Pattern.compile(regex);//编译
        Matcher matcher = pattern.matcher(str1);
        System.out.println(matcher.matches());
    }
}

结果:

true

  如果纯粹的是以拆分、替换、匹配三种操作为例根本用不到java.util.regex开发包,只依靠String类就都可以实现了。<mark>但是Matcher类里面提供有一种分组的功能,而这种分组的功能是String不具备的。</mark>

代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws ParseException {
        String str1 = "INSERT INTO dept(deptno,dname,loc) VALUES (#{deptnp},#{dname},#{loc})";//要匹配的数据
        String regex = "#\\{\\w+\\}";//正则规则
        Pattern pattern = Pattern.compile(regex);//编译
        Matcher matcher = pattern.matcher(str1);
        while (matcher.find()){//是否有匹配的内容
            System.out.println(matcher.group(0).replaceAll("#|\\{|\\}",""));
        }
    }
}

结果:

deptnp
dname
loc

  java.util.regex开发包,如果不是进行一些更为复杂的正则处理是很难使用到的,而String类所提供的功能只适合于正则的基本操作。