黑马程序员——正则表达式1:概述

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


1  正则表达式简介

1.1  正则表达式的概念

       正则表达式是一种强大而灵活的文本处理工具。使用正则表达式,我们能够以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索。一旦找到了匹配这些模式的部分,你就能够随心所欲地对它们进行处理了(摘自《Java编程思想》)。简单一句话,正则表达式就是专门用于操作字符串的,符合一定规则的表达式。

1.2  正则表达式的优缺点

       我们在前面的《字符串》系列博客中,曾经详细介绍过有关操作字符串的各种方法,但是这些方法的功能都较为简单,而组合起来实现复杂功能时,相应的代码又过于复杂。正则表达式则可以使用较少的代码,同时实现较为复杂的字符串操作。

但是相应的越是复杂的字符串操作,对应的正则表达式就越复杂,阅读性也随之降低。这是正则表达式的弊端。

1.3  与传统方法的对比

       我们先来看一个例子,通过这个例子来了解不使用正则表达式,而通过常规方法来进行复杂字符串操作的麻烦之处。

需求:对QQ号码进行校验。要求:能够对长度为5~15位的QQ号码进行校验,并且首位不能为0,号码中不能包含非数字字符。

思路:依次判断QQ号码长度、首位字符,以及循环判断号码中是否包含非数字字符。

代码1:

class RegexDemo
{
	public static void main(String[] args)
	{
		String[] qqNumbers = {"9008", "1895828587923545452", "0123456", "458b16m54", "567890123"};
 
		for(int i = 0; i<qqNumbers.length; i++){
			isQQCount(qqNumbers[i]);
		}    
	}
	public static void isQQCount(String qqNumber)
	{
		int numLen = qqNumber.length();
             
		//首先判断QQ号码长度
		if(numLen >= 5 && numLen <= 15){
			//其次判断QQ号码首位是否是0
			if(!(qqNumber.charAt(0)== '0')){
				char[]temp = qqNumber.toCharArray();
				char c;
				//循环判断QQ号码中是否包含非数字字符
				for(int i = 0; i<numLen; i++){
					c = temp[i];
					if(c< '0' || c > '9'){
						/*
							一旦检测出包含有非数字字符
							给出错误提示,并立即停止检测
						*/
						System.out.println("QQ号码中不能包含非数字字符!");
						return;
					}
				}
 
				//未检测处非法字符,则给出正确提示
				System.out.println(qqNumber+":该QQ通过验证!");
			}
			else{
				System.out.println("QQ号码不能以0开头!");
			}
		}
		else
			System.out.println("QQ号码长度错误!");
	}
}
以上代码的执行结果为:

9008:QQ号码长度错误!

1895828587923545452:QQ号码长度错误!

0123456:QQ号码不能以0开头!

458b16m54:QQ号码中不能包含非数字字符!

567890123:该QQ通过验证!

       以上代码是从字符串的角度,对QQ号码进行验证,我们还可以利用基本数据类型包装类的转换方法,让Java帮助我们进行判断。

思路2:号码长度和首位判断与思路1是一样的,而其他位号码的判断可以通过Long类的静态方法parseLong实现,如果尝试将包含非数字字符的字符串转换为长整型时,将抛出异常。

代码2:

public static void isQQCount2(String qqNumber)
{
	int numLen = qqNumber.length();
             
	if(numLen >= 5 && numLen <= 15){
		if(!(qqNumber.charAt(0) == '0')){
			try{
				//将QQ号码字符串转换为长整型值
				long qqNumberLongFormat = Long.parseLong(qqNumber);
				//若转换成功,表示QQ号码验证成功
				System.out.println(qqNumberLongFormat+":该QQ通过验证!");
			}
			catch(NumberFormatException e){
				//若抛出异常,则表示QQ号码中包含了非数字字符,给出错误提示
				System.out.println(qqNumber+":QQ号码中不能包含非数字字符!");
			}
		}
		else
			System.out.println(qqNumber+":QQ号码不能以0开头!");
	}
	else
		System.out.println(qqNumber+":QQ号码长度错误!");
}
通过以上方法进行验证的结果为:

9008:QQ号码长度错误!

1895828587923545452:QQ号码长度错误!

0123456:QQ号码不能以0开头!

458b16m54:QQ号码中不能包含非数字字符!

567890123:该QQ通过验证!

       执行结果表明,第二种方法同样实现了QQ号码的验证功能。下面我们再来演示如何通过正则表达式来对QQ号码进行验证,并将常规方法和正则表达式进行对比。

在给出演示代码以前,我们首先介绍一个用于匹配字符串内容的String类方法——matches:

       public boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。该方法的参数名regex就是字符串形式的正则表达式,那么matches方法就通过读取这一表达式的含义,来判断调用该方法的字符串内容符合该表达式所规定的规则。

代码3:

public static void isQQCount3(String qqNumber)
{
	//定义正则表达式
	String regex = "[1-9][0-9]{4,14}";
 
	//使用以上正则表达式对目标QQ号码字符串进行匹配
	boolean flag = qqNumber.matches(regex);
	if(flag)
		System.out.println(qqNumber+":该QQ号码通过验证!");
	else
		System.out.println(qqNumber+":该QQ号码格式错误!");
}
9008:该QQ号码格式错误!

1895828587923545452:该QQ号码格式错误!

0123456:该QQ号码格式错误!

458b16m54:该QQ号码格式错误!

567890123:该QQ号码通过验证!

代码说明:

       我们对代码3中出现的正则表达式含义进行一个简单的解释。首先正则表达式是按照字符串的位置来进行判断的。第一对方括号“[1-9]”表示,第一位字符串必须是在1-9之间的数字;第二对方括号“[0-9]”表示,第二位字符串必须是在0-9之间的数字;紧接着的一对大括号“{4,14}”表示第2到第15位字符串要重复使用第二对方括号的规则进行判断。

       对比前两种方法和第三种方法,从代码量的角度来说,显然通过正则表达式对字符串QQ号码进行验证是最为方便的。由此可以非常明显的表明正则表达式在字符串操作方面的优势。

2  正则表达式的定义规则

       那么通过对以上需求的演示可知,正则表达式的作用,就是用一些特定的符号来代表一些代码操作,而不必显示地将这些代码写出来,因此起到了简化代码书写的作用。那么我们学习正则表达式,其实就是在学习一些特殊符号的使用,通过这些符号的组合来,来达到对字符串进行操作的目的。下面我们就来介绍正则表达式中常用的一些符号。在标准类库java.util.regex包Pattern类的API文档中,详细介绍了正则表达式中常用的符号,这里我们对这些字符作一个简单的介绍,并在第二节《正则表达式的功能》中来演示这些符号的用法。

(1)  字符

       实际就是我们常用的基本常见字符,比如代码制表符的“\t”、代表换行符的“\n”、代表回车符的“\r”等等,因此这里不再赘述。

(2)  字符类

       字符类代表了专门用于操作字符的符号。书写规则为:一对方括号“[]”内包含了一些字符,表示字符串中某一位字符必须包含在这一对方括号内的字符范围内,比如a-z表示小写字母范围,A-Z表示大写字母范围,0-9表示数字范围。因为字符类的定义规则较为简单,因此请大家自行查阅JavaAPI文档。

(3)  预定义字符类

       这一类字符通常通过一个字符来代表一个字符范围。这里有一个需要注意的地方,以表示数字的“\d”为例。在字符串中,单个出现的“\”表示转义字符,它可以将后面的字符串转义为其他含义,而“\”本身不包含在字符串内容中。但是预定义字符“\d”是一个整体,也就是说,“\”+“d”才能表示任意数字。因此在字符串形式的正则表达式中,若要使用“\d”则必须在其前面再加一个“\”,将后一个“\”转义为反斜线,而不是转义字符,因此表达式为“\\d”。

(4)  数量词

       由以上所述内容可知,一对方括号,或者一个预定义字符,只能用于匹配一个字符串位上的字符。如果为了定义若干位置上的字符,则需要重复定义多个方括号对,或者预定义字符,将导致整个正则表达式非常冗长。因此可以在匹配一个字符的表达式后接数量词,表示后面的字符将重复匹配这一个规则,使得正则表达式更为简洁。

(5)  组

       假如我们要匹配重复出现的字符,比如“kkk”,“qq”,“***”,“##”等等时,该如何去定义正则表达式呢?如果第一位使用“.”去匹配任意字符,那么第二位以及以后的字符位上的字符该如何保证和第一位一样呢?此时显然不能再使用“.”了,因为它同样表示任意字符,而不是对第一个匹配字符的引用。此时我们就可以使用组的概念。

       将某一位规则用一对“()”括起来,表示一个组。当这一组所表示的字符匹配以后,通过引用这一组,即可继续向后匹配相同的字符。引用的方法为,在组后面加“\”+数字的形式,比如“\1”表示第一组,“\0”第0组,代表整个正则表达式。当然,由于转义字符的问题,还应该在“\1”前再加一个“\”。 

       引入组的概念以后,慢慢体现出了正则表达式规则的复杂性,这也就是它的弊端。

 

小知识点1:

       当组的定义非常复杂时,比如JavaAPI文档中的例子——“((A)(B(C)))”,该如何去判断组的个数呢?窍门就是数左括号“(”的个数,例子中共有4个左括号,对应有4个组。按照左括号从做到右的顺序,“((A)(B(C)))”为第一组,“(A)”为第二组,“(B(C))”为第三组,“(C)”为第四组。

 

(6)  边界匹配器

       若从一个英文语句中获取匹配某个正则表达式规则的单词时,就需要用到单词边界——“\b”。由于英文语句的单词都是通过空格进行分隔,因此表示某个规则的正则表达式前后分别添加单词边界“\b”即可将某个单词从英文语句字符串中取得。其他边界匹配器,请大家参考正则表达式API文档。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值