您的位置:首页 > 编程语言

代码即财富之我学正则表达式

2015-07-03 00:00 309 查看
摘要: 正则表达式主要用途是文本规则的匹配和验证,在处理字符串的程序或网页时,经常需要对用户输入进行正则验证,从而简化复杂的程序编写逻辑,因此,正则表达式实际上就是一种文本规则的验证工具。

在正则表达式诞生之前,通常我们对某一字符串文本进行验证的时候,需要编配大量的匹配规则,尤其出现在需要用户输入的地方,比如对用户输入的用户名,密码和邮箱进行输入验证,如果存在非法字符,则可能认为是恶意输入。下面通过Java语言介绍一个没有使用正则表达式的邮箱输入验证案例。

给定一个邮箱:aB-c_d.ef@g1_2-3h.i4_J-k(其中的空格实际上是下划线,显示问题)

对于该邮箱(任意邮箱),我们将其划分为3个部分,首先,邮箱一定至少包含一个"."号且只包含一个"@"符号,以这两个符号将邮箱分成3部分,第一部分为@之前的内容,可以是任意字母,数字,中划线,下划线,点号;第二部分为@与最后一个点号之间的内容,可以是任意字母,数字,中划线,下划线,但不可以是点号;第三部分为最后一个点号一直到结尾处的内容,实际上应该是域名,为了简化,我们认为此处内容也可以是任意字母,数字,下划线,中划线,但不可以是点号。

明白以上规则之后,见代码

public static boolean isDigit(char c){
if(c >= '0' && c <= '9'){
return true;
}else{
return false;
}
}
public static boolean isLetter(char c){
if((c >= 'a' && c <= 'z') || (a >= 'A' && a<= 'Z')){
return true;
}else{
return false;
}
}
public static boolean commVerify(String emailStr){
boolean flag = true;
if(emailStr.indexOf(".") == -1 || emailStr.indexOf("@") == -1){
flag = false;
}else{
int highIndex = emailStr.lastIndexOf(".");
String highStr = emailStr.substring(highIndex+1);
System.out.println(highStr);
char highChars[] = highStr.toCharArray();
for(int i=0;i<highChars.length;i++){
if(!isDigit(highChars[i]) && !isLetter(highChars[i]) && highChars[i] != '-' && highChars[i] != '_'){
flag = false;
break;
}
}
int middleIndex = emailStr.indexOf("@");
String middleStr = emailStr.substring(middleIndex+1,highIndex);
System.out.println(middleStr);
char middleChars[] = middleStr.toCharArray();
for(int i=0;i<middleChars.length;i++){
if(!isDigit(middleChars[i]) && !isLetter(middleChars[i]) && middleChars[i] != '-' && middleChars[i] != '_'){
flag = false;
break;
}
}
int lowIndex = 0;
String lowStr = emailStr.substring(0,middleIndex);
System.out.println(lowStr);
char lowChars[] = lowStr.toCharArray();
for(int i=0;i<lowChars.length;i++){
if(!isDigit(lowChars[i]) && !isLetter(lowChars[i]) && lowChars[i] != '-' && lowChars[i] != '_' && lowChars[i] != '.'){
System.out.println(lowChars[i]);
flag = false;
break;
}
}

}
return flag;
}

以上代码虽然可以实现邮箱规则的匹配,但是各种条件语句和循环语句的嵌套导致结构不清晰,代码量多。如何改用正则表达式呢。这便是本文要介绍的问题。

正则表达式是一种文本规则描述的匹配工具,其规则和语法非常多,也不需要全部记住,但对最基本的一定要牢记,最基本最简单的正则表达式就是文本字符串本身, 用于匹配与该字符串相等的字符串。

[]表选择

表达式描述
[abc] 表示取值可以是a,可以是b,也可以是c
[^abc]表示取值不是abc中的任意字符,即除abc以外的内容
[a-zA-Z]表示所有字母,大写和小写,[a-z]表示小写字母,[A-Z]表示大写字母
常用元字符

表达式描述
.除换行符以外的任意字符
\d所有数字
\w所有字母,数字,下划线
\s所有空白字符
\b单词边界位置
^字符串开始
$字符串结尾
常用的反义字符

表达式描述
\D非数字
\W非字母、数字、下划线
\S非空白字符
\B非单词开始或结束边界位置
表示出现的次数

表达式描述
X?表示出现0次或1次
X*表示出现0次或多次
X+表示出现1次或多次
X{n}表示出现n次
X{n,}表示出现的长度大于n次
X{n,m}表示出现n到m次
关系运算

表达式描述
X|Y表示要么是X的正则,要么是Y的正则
(X)表示一组规范,一个分组
介绍了以上的正则表达式及其表示含义之后,大家都或多或少了解了一些相关知识,现在顺便介绍一下正则表达式的贪婪匹配和惰性匹配策略。一般匹配都是遵循贪婪匹配策略,即尽可能多地匹配,而以下规则支持惰性匹配,即尽可能少地匹配

表达式描述
*?重复任意次,但尽可能少地重复
+?重复1次或多次,但尽可能少地重复
??重复0次或1次,但尽可能少地重复
{n,m}?重复n到m次,尽可能少地重复
{n,}?重复至少n次,但尽可能少地重复
下面就上面介绍地邮箱验证的例子,我们给出使用正则表达式进行规则匹配的案例,对比之下,可以发现,使用正则表达式,不但能使程序结构清晰,也大大简化了代码量和我们的逻辑判断工作。

JAVA对正则表达式有着良好地支持,自JDK1.4,它提供了java.util.regex包,主要负责正则匹配的两个类为Pattern类和Matcher类,Pattern根据指定正则表达式字符串构建匹配模式,并利用matcher方法返回Matcher类对象实例,用于完成匹配,实际的匹配是交给Matcher完成的,Pattern类对象的构造是通过静态方法compile构造。

public static boolean regexVerify(String emailStr){
Pattern p = Pattern.compile("[\\w-\\.]+@[\\w-]+\\.[\\w-]+");
Matcher m = p.matcher(emailStr);
if(m.matches())
//if(emailStr.matches("[\\w-\\.]+@[\\w-]+\\.[\\w-]+"))//String object has a good support to regexp
return true;
else
return false;
}

从以上代码可以看出,使用Java的正则表达式可以快速完成与大量逻辑判断相同的工作,且结构清晰,只要定义的正则表达式正确,其实在Java中一般不直接使用Pattern类和Matcher类完成正则模式匹配,因为正则匹配的对象都是文本字符串,目的就是为了验证文本规则,而String在Java中又是一个及其特殊的类,因此自从JDK1.4,引进正则表达式,String类就作了相应的修改,提供了split,matches,replaceAll,replaceFirst等方法。如上述代码注释的内容即为直接使用String对象的matches方法,其效果是完全一样的。

另外我想延伸的一点是,上述程序代码即正则表达式规则,虽然能够判别邮箱,但是邮箱通过的域名都是有限的(如163.com,qq.com),因此,本文提供精确的邮箱认证方式,即登录到邮箱服务器,验证邮箱是否存在,并返回验证结果。该功能需要Appache 的common-net.jar和dnsjava.jar包的支持。

public static boolean verifyDNS(String emailStr) {
String host = "";
String hostName = emailStr.split("@")[1];
Record[] result = null;
SMTPClient client = new SMTPClient()
try {
// 查找MX记录
Lookup lookup = new Lookup(hostName, Type.MX);
lookup.run();
if (lookup.getResult() != Lookup.SUCCESSFUL) {
return false;
} else {
result = lookup.getAnswers();
}

// 连接到邮箱服务器
for (int i = 0; i < result.length; i++) {
host = result[i].getAdditionalName().toString();
client.connect(host);
if (!SMTPReply.isPositiveCompletion(client.getReplyCode())) {
client.disconnect();
continue;
} else {
break;
}
}
client.login("xxxxxxxxxxxxxxxz.com");
client.setSender();

client.addRecipient(emailStr);
if (250 == client.getReplyCode()) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
client.disconnect();
} catch (Exception e) {
}
}
return false;
}

这部分代码拷贝至http://www.eziep.net/details/80.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: