正则表达式匹配常用字符(只含常用):

字符:

x 字符x
\n 新行(换行)符 ('\u000A')
\t 制表符 ('\u0009')

字符类:

[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:[a-lq-z](减去)

预定义字符类:

. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]

边界匹配器:

\b 单词边界
\B 非单词边界

Greedy 数量词:

X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次

例子:检查 QQ 号

public class Main {
    public static void main(String args[]) {
        String QQ="a1234";
        //[1-9]第一位在1-9中间,[0-9]第二位在0-9之间,{4,14}代表0-9重复4~14遍
        //String.matches(regex);判断字符串是否符合正则表达式
        //等价于boolean b=QQ.matches("[1-9]\\d{4,14}");
        boolean b=QQ.matches("[1-9][0-9]{4,14}");
        System.out.println(b);
    }
}
public class Main {
    public static void main(String args[]) {
        String QQ="a1234";
        boolean b=QQ.matches("a[1-9]\\d+");//+代表1-9出现1次或多次  true
        System.out.println(b);
        b=QQ.matches("a[1-9]\\d?");//+代表1-9出现0次或一次  false
        System.out.println(b);
        b=QQ.matches("a[1-9]\\d*");//+代表1-9出现0次或多次  true
        System.out.println(b);
    }
}

正则表达式的四项功能:

1、匹配

例子:校验手机号是否正确

public class Main {
    public static void main(String args[]) {
        String tel="15800001111";
        //第一位1,第二位3或者5或者8,\\d{9}代表0-9出现了9次
        String regex="1[358]\\d{9}";
        boolean b=tel.matches(regex);
        System.out.println(b);//true
    }
}

2、切割

例子:名字切割(一个或多个空格)

public class Main {
    public static void main(String args[]) {
        String temp="zhangsan   lisi   wangwu";//中间多个空间,不能使用split(" ")切割
        String regex=" +";
        String[] names=temp.split(regex);
        for (String name : names) {
            System.out.println(name);
        }
    }
}

例子:用.(点)切割

public class Main {
    public static void main(String args[]) {
        String temp="zhangsan.lisi.wangwu";
        //.在正则表达式代表任意字符,有特殊含义,需要转义才能用.分割
        String regex="\\.";
        String[] names=temp.split(regex);
        for (String name : names) {
            System.out.println(name);
        }
    }
}

重点:捕获组的概念

小括号括起来叫一个组,系统自动给序号,第 x 个左括号是第 x 组,组的下标从 1 开始,0 是特殊组,代表整个表达式,比如在本字符串中调用第 1 组需要使用\1,在其他的字符串中调用第 1 组需要使用 $1

编号例子:在表达式((A)(B(C)))中有四组:

1 ((A)(B(C)))
2 (A)
3 (B(C))
4 (C)

捕获组例子:切割叠词:

public class Main {
    //运行结果que  teg  iou  abc
    public static void main(String args[]) {
        String temp="que###teg$$$$$$$iouzzzzzzzzzzabc";
        //(.)这是一个组,\\1调用这个组,代表本字符第2次出现,+代表一次或者多次
        //也就是一个字符出现两次或者两次以上,以叠词切割
        String regex="(.)\\1+";
        String[] names=temp.split(regex);
        for (String name : names) {
            System.out.println(name);
        }
    }
}

3、替换

例子:隐藏手机号

public class Main {
    //运行结果159****1111
    public static void main(String args[]) {
        String temp="15900001111";
        //利用捕获组将手机号分为3组,在第二个字符串中调用这两个捕获组
        temp=temp.replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
        System.out.println(temp);
    }
}

例子:将叠词变为一个

public class Main {
    //运行结果:qwe#tyg$iouzsdf
    public static void main(String args[]) {
        String temp="qwe##tyg$$$$$$iouzzzzzzzsdf";
        temp=temp.replaceAll("(.)\\1+","$1");
        System.out.println(temp);
    }
}

4、获取

Pattern 类: 正则表达式的编译表示形式,通常使用其 static Pattern compile(String regex)方法将给定的正则表达式编译到模式中。例如:Pattern p=Pattern.compile(regex);将规则编译成对象。

Matcher 类: 充当通过解释 Pattern 对字符序列执行匹配操作的引擎。

例如:Matcher m=p.matcher("aaaaab");与要操作的字符串进行关联,生成匹配器对象。

Matcher 常用的三个方法:

boolean matches();尝试整个区域与模式匹配

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Main {
    public static void main(String args[]) {
        String temp = "aaa111";
        String regex=".{6}";
        //将规则编译成Pattern对象
        Pattern p = Pattern.compile(regex);
        //和字符串关联,获取匹配器对象
        Matcher m = p.matcher(temp);
        //整体匹配,结果为true
        System.out.println(m.matches());
    }
}

boolean lookingAt();尝试将从区域开头开始的输入序列与该模式匹配。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Main {
    public static void main(String args[]) {
        String temp = "aaa111";
        String regex=".{3}";
        //将规则编译成Pattern对象
        Pattern p = Pattern.compile(regex);
        //和字符串关联,获取匹配器对象
        Matcher m = p.matcher(temp);
        //开头匹配,结果为true
        System.out.println(m.lookingAt());
    }
}

boolean find();重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Main {
    //运行结果jia  zhu   jia
    public static void main(String args[]) {
        String temp = "da jia zhu yi le,ming tian fang jia le!";
        //取出由三个字母组成的单词
        String regex = "\\b[a-zA-Z]{3}\\b";//\\b为边界
        //将规则编译成Pattern对象
        Pattern p = Pattern.compile(regex);
        //和字符串关联,获取匹配器对象
        Matcher m = p.matcher(temp);
        while(m.find()){
            System.out.println(m.group());
        }
    }
}

int end();返回最后匹配字符之后的偏移量。

String group();返回由以前匹配操作所匹配的输入子序列。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Main {
    //运行结果
    // 3:jia:6
    //7:zhu:10
    //32:jia:35
    public static void main(String args[]) {
        String temp = "da jia zhu yi le,ming tian fang jia le!";
        //取出由三个字母组成的单词
        String regex = "\\b[a-zA-Z]{3}\\b";//\\b为边界
        //将规则编译成Pattern对象
        Pattern p = Pattern.compile(regex);
        //和字符串关联,获取匹配器对象
        Matcher m = p.matcher(temp);
        while(m.find()){
            System.out.println(m.start()+":"+m.group()+":"+m.end());
        }
    }
}

练习:

练习一:去结巴

public class Main {
    //运行结果:我要学编程
    public static void main(String args[]) {
        String temp="我我...我我我...我要要要..要要.学学学..学学编.编编..编编程程.程.程程";
        temp=temp.replaceAll("\\.","");//去点
        temp=temp.replaceAll("(.)\\1+","$1");//去叠词
        System.out.println(temp);
    }
}

练习二:ip 排序

import java.util.Arrays;
 
public class Main {
    public static void main(String args[]) {
        String temp="192.168.1.200  17.10.10.10   3.3.50.3   127.0.0.1";
        //排序方法:将所有连续数字加两个0后去后三位即可排序。
        //补两个0
        temp=temp.replaceAll("(\\d+)","00$1");
        //保留最后每段3位
        temp=temp.replaceAll("0*(\\d{3})","$1");
        String[] ips=temp.split(" +");
        Arrays.sort(ips);
        for (String ip : ips) {
            System.out.println(ip.replaceAll("0*(\\d+)","$1"));//去除前面的0
        }
    }
}

练习三:邮箱验证

public class Main {
    public static void main(String args[]) {
        String mail="abc12@sina.com";
        //\\w代表字母数字下换线,+代表一个或者多个,@固定字符,@后面一个或者多个字母数字,然后就是.和.后面的2~3个字母,例如.com
        //然后就是.com重复1~3遍
        String regex="\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,3}){1,3}";
        boolean b=mail.matches(regex);
        System.out.println(b);
    }
}

补充

正则表达中为什么要使用两个//而不是一个/,比如//.?
解释:这要分两步看,首先字符串中的\\被编译器解释为\,然后作为正则表达式“\.”又被正则表达式引擎解释为“.”如果在字符串里只写“\.”的话,第一步就被直接解释为“.”,之后作为正则表达式被解释时就变成匹配任意字符了。