Java 正则表达式详解

正则表达式是由普通字符(如英文字母)以及特殊字符(也称为元字符)组成的文字模式。该模式对文本查找时需要匹配的一个或多个字符串描述,给出一个匹配模板。它专门用于操作字符串,可以简化对字符串的复杂操作。

符号定义

基本书写符号

符号
符号
示例
解释
匹配输入
 \ 
转义符
\* 
符号“*”
*
[  ] 
可接收的字符列表
[efgh]
e、f、g、h中的任意1个字符
e、f、g、h
[^] 
不接收的字符列表
[^abc]
除a、b、c之外的任意1个字符,包括数字和特殊符号 
m、q、5、* 
 |
匹配“|”之前或之后的表达式 
ab|cd
ab或者cd
ab、cd
(  ) 
将子表达式分组 
(abc)
将字符串abc作为一组
abc 
 - 
连字符
A-Z
任意单个大写字母 
大写字母

限定符

限定符将可选数量的数据添加到正则表达式,下表为常用限定符:

符号
含义
示例
示例
匹配输入
不匹配输入
*  
指定字符重复0次或n次 
(abc)*
仅包含任意个abc的字符串,等效于\w*
abc、abcabcabc
a、abca

指定字符重复1次或n次
m+(abc)* 
以至少1个m开头,后接任意个abc的字符串
m、mabc、mabcabc
ma、abc
? 指定字符重复0次或1次
m+abc?
以至少1个m开头,后接ab或abc的字符串
mab、mabc、mmmab、mmabc
ab、abc、mabcc
{n}
只能输入n个字符 
[abcd]{3}
由abcd中字母组成的任意长度为3的字符串
abc、dbc、adc
a、aa、dcbd
{n,}
指定至少 n 个匹配
[abcd]{3,}
由abcd中字母组成的任意长度不小于3的字符串 
aab、dbc、aaabdc
a、cd、bb
{n,m}
指定至少 n 个但不多于 m 个匹配 
[abcd]{3,5}
由abcd中字母组成的任意长度不小于3,不大于5的字符串
abc、abcd、aaaaa、bcdab
ab、ababab、a
^
指定起始字符 
^[0-9]+[a-z]*
以至少1个数字开头,后接任意个小写字母的字符串
123、6aa、555edf
abc、aaa、a33
$
指定结束字符
^[0-9]\-[a-z]+$
以1个数字开头后接连字符“–”,并以至少1个小写字母结尾的字符串
2-a、3-ddd、5-efg
33a、8-、7-Ab

匹配字符集

匹配字符集是预定义的用于正则表达式中的符号集。如果字符串与字符集中的任何一个字符相匹配,它就会找到这个匹配项。

正则表达式中的部分匹配字符集:

符号
含义
示例
示例
匹配输入
不匹配输入
.   
匹配除 \n 以外的任何字符 
a..b
以a开头,b结尾,中间包括2个任意字符的长度为4的字符串
aaab、aefb、a35b、a#*b
ab、aaaa、a347b
\d 
匹配单个数字字符,相当于[0-9]
\d{3}(\d)?
包含3个或4个数字的字符串
123、9876
123、9876
\D  匹配单个非数字字符,相当于[^0-9]
\D(\d)*
以单个非数字字符开头,后接任意个数字字符串
a、A342 aa、AA78、1234
\w
匹配单个数字、大小写字母字符,相当于[0-9a-zA-Z]
\d{3}\w{4}
以3个数字字符开头的长度为7的数字字母字符串
234abcd、12345Pe
58a、Ra46
\W
匹配单个非数字、大小写字母字符,相当于[^0-9a-zA-Z]
\W+\d{2}
以至少1个非数字字母字符开头,2个数字字符结尾的字符串
#29、#?@10
23、#?@100

分组构造

常用分组构造形式:

常用分组构造形式 说明
() 非命名捕获。捕获匹配的子字符串(或非捕获组)。编号为零的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺序从1开始自动编号。 
(?<name>) 命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如 (?'name') 

字符转义

如果你想查找元字符本身的话,比如你查找.,或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。当然,要查找\本身,你也得用\\
例如:deerchao\.net匹配deerchao.NET,C:\\Windows匹配C:\Windows。注意在Java中: (https://github\\.com/[\\w\\-]) 用"\\."配备"."。

常用正则表达式举例

非负整数:“^\d+$ ”
正整数: “ ^[0-9]*[1-9][0-9]*$” 
非正整数: “ ^((-\d+)|(0+))$” 
整数: “ ^-?\d+$” 
英文字符串: “ ^[A-Za-z]+$” 
英文字符数字串: “ ^[A-Za-z0-9]+$” 
英数字加下划线串: “^\w+$” 
E-mail地址:“^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$” 
URL:“^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$” 

JAVA正则表达式Pattern和Matcher

Pattern是一个正则表达式经编译后的表现模式,而Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 如果要详细了解这2个类如何操作正则表达式,请看pattern类详解matcher类详解。下面用几个例子说明在java中如何利用正则表达式进行字符串操作。

对QQ号码进行校验

//对QQ号码进行校验; 需求:长度为5~15,不能以0开头,全都为数字;  
public static void checkQQ_1() //使用正则表达式操作;  
{
    String QQ = "164a35464165";
    String QQReg = "[1-9]\\d{4,14}";
    boolean checkResult = QQ.matches(QQReg);
    if (checkResult) System.out.println("QQ :" + QQ);
    else System.out.println("非法QQ!!!");
}

字符串操作替换

public static void main(String[] args) {
    /* 为了让规则的结果可以被重用,可以将规则封装成一个组,用()来完成。组的出现都有编号。 
        编号从1开始,要想使用已有的组,可以通过\n(n就是组的编号)的形式来获取。          
        */
    String str1 = "dfhk6426543541sdfg4565263dggr123456789";
    replaceAllDemo(str1, "\\d{5,}", "*"); //将数字替换成*;  
    String str = "kjsdffjeihgglsjssskfjkkklc";
    replaceAllDemo(str, "(.)\\1+", "$1"); //将重叠的字符替换成单个字符;替换结果:kjsdfjeihglsjskfjklc  
}

public static void replaceAllDemo(String str, String reg, String newStr) {
    str = str.replaceAll(reg, newStr);
    System.out.println(str);
}

字符串操作切割

public static void main(String[] args) {
    splitDemo("java01  java02 java03    java04", " +"); //" +"是按照多个空格来切割;  
    splitDemo("D:\\mytest\\day225\\RegexDemo.java", "\\\\");
    splitDemo("kjsdffjeihgglsjssskfjkkklc", "(.)\\1+"); //按照叠词切割;  
}
public static void splitDemo(String str, String reg) {
    String[] arr = str.split(reg);
    for (String s: arr) {
        System.out.println(s);
    }
}

字符串操作查找

public static void getDemo() {
    String str = "ming tian jiu yao fang jia le, da jia.";
    String reg = "\\b[a-z]{4}\\b";
    //将规则封装成对象;  
    Pattern p = Pattern.compile(reg);
    //让正则对象和要操作的字符串相关联;  
    Matcher m = p.matcher(str);

    //m.find():将规则作用到字符串上,并进行符合规则的字串查找;  
    while (m.find()) {
        System.out.println(m.group());
        System.out.println(m.start() + "---" + m.end()); //获取找到字串的始末索引(包含头,不包含尾);  
    }
}

字符串包含验证

//查找以Java开头,任意结尾的字符串
Pattern pattern = Pattern.compile("^Java.*");
Matcher matcher = pattern.matcher("Java不是人");
boolean b= matcher.matches();
//当条件满足时,将返回true,否则返回false
System.out.println(b);

例子

//正则表达式测试
public class MatcherTest {
    public static void main(String[] args) throws Exception {
        //生成Pattern对象并且编译一个简单的正则表达式"Kelvin"   
        Pattern p = Pattern.compile("Kelvin");
        //用Pattern类的matcher()方法生成一个Matcher对象   
        Matcher m = p.matcher("Kelvin Li and Kelvin Chan are both working in Kelvin Chen's KelvinSoftShop company");
        StringBuffer sb = new StringBuffer();
        int i = 0;
        //使用find()方法查找第一个匹配的对象   
        boolean result = m.find();
        //使用循环将句子里所有的kelvin找出并替换再将内容加到sb里   
        while (result) {
            i++;
            m.appendReplacement(sb, "Kevin");
            System.out.println("第" + i + "次匹配后sb的内容是:" + sb);
            //继续查找下一个匹配对象   
            result = m.find();
        }
        //最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里;   
        m.appendTail(sb);
        System.out.println("调用m.appendTail(sb)后sb的最终内容是:" + sb.toString());
    }
}

执行结果:

第1次匹配后sb的内容是:Kevin 
第2次匹配后sb的内容是:Kevin Li and Kevin 
第3次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin 
第4次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's Kevin 

总结

1. 搜索(匹配):在一个字符串中搜索出一个或多个与正则表达式相匹配的子字符串。搜索又分为匹配和子字符串搜索。匹配是对用户所提供的整个字符串进行判断,看其是否匹配正则表达式,比如电子邮件地址的匹配。子字符串搜索是“搜索”的普遍含义,指的是将与正则表达式相匹配的所有子字符串找出来,比如将一段英文文本中的所有单词给找出来。 

2. 替换(匹配并替换):将一个字符串中与正则表达式相匹配的子字符串找出来并替换成另一些子字符串,比如将一个字符串中的所有的cos替换成sin。

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。