博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代码即财富之我学正则表达式
阅读量:6697 次
发布时间:2019-06-25

本文共 4287 字,大约阅读时间需要 14 分钟。

hot3.png

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

给定一个邮箱:(其中的空格实际上是下划线,显示问题)

 对于该邮箱(任意邮箱),我们将其划分为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

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

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

[]表选择

 表达式 描述
[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;    }

这部分代码拷贝至。

转载于:https://my.oschina.net/u/1258323/blog/474345

你可能感兴趣的文章