《疯狂java讲义》学习(25):处理日期的类

版权声明:本文为博主原创文章,如若转载请注明出处 https://blog.csdn.net/tonydz0523/article/details/86656227

正则表达式

正则表达式是强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。String类里也提供了几个特殊的方法:

  • boolean matches(String regex):判断该字符串是否匹配指定的正则表达式。
  • String replaceAll(String regex, String replacement):将该字符串中所有匹配regex的子串替换成replacement。
  • String replaceFirst(String regex, String replacement):将该字符串中第一个匹配regex的子串替换成replacement。
  • String[] split(String regex):以regex作为分隔符,把该字符串分割成多个子串。

上面这些特殊的方法都依赖于Java提供的正则表达式支持,除此之外,Java还提供了Pattern和Matcher两个类专门用于提供正则表达式支持。

创建正则表达式

正则表达式就是用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串,由合法字符和特殊字符组成:
合法字符详细:
在这里插入图片描述
特殊字符详细:
在这里插入图片描述
将上面多个字符组合使用即可创建正则表达式:

"\\u0041\\"  //匹配a\
"\\0101\t"   //匹配a<制表符>
"\?\["   //匹配?[

上面的正则表达式依然只能匹配单个字符,这是因为还未在正则表达式中使用“通配符”,“通配符”可以匹配多个字符,这里我们将其称为预定于字符:
在这里插入图片描述

上面的7个预定义字符其实很容易记忆——d是digit的意思,代表数字;s是space的意思,代表空白;w是word的意思,代表单词。d、s、w的大写形式恰好匹配与之相反的字符。

有了预定义字符后,就可以更方便的创建正则表到式:

c\wt  //可以匹配cat、cbt、cct、c0t、c9t等一批字符串
\d\d\d-\d\d\d-\d\d\d\d  //匹配如000-000-0000形式的电话号码

在一些特殊情况下,例如,若想匹配a~f的字母,或者匹配除了ab之外的所有小写字母,或者匹配中文字符,这里我们可以使用方括号表达式:
在这里插入图片描述
正则表示还支持圆括号表达式,用于将多个表达式组成一个子表达式,圆括号中可以使用或运算符(|)。例如,正则表达式"(public|protected|private)"用于匹配Java的三个访问控制符其中之一。
正则还支持对头尾的匹配,使用边界匹配符:
在这里插入图片描述

正则表达式还提供了数量标识符,正则表达式支持的数量标识符有如下几种模式。

  • Greedy(贪婪模式):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。如果你发现表达式匹配的结果与预期的不符,很有可能是因为——你以为表达式只会匹配前面几个字符,而实际上它是贪婪模式,所以会一直匹配下去。
  • Reluctant(勉强模式):用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。
  • Possessive(占有模式):用加号后缀(+)表示,目前只有Java支持占有模式,通常比较少用
    三种模式数量表示符:
    在这里插入图片描述
    关于贪婪模式和勉强模式的对比,看这个例子:
String str="hello , java!";
//贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*" , "■"));       //输出■ , java!
//勉强模式的正则表达式
System.out.println(str.replaceFirst("\\w*?" , "■"));      //输出■hello , java!

正则表达式的使用

一旦在程序中定义了正则表达式,就可以使用Pattern和Matcher来使用正则表达式。
Pattern对象时正则表达式编译后的内存中的表示形式,因此,正则表达式字符串必须先被编译成为Pattern对象,然后在利用该Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留在Matcher对象中,多个Matcher对象可共享同一个Pattern对象。
因此,典型的调用顺序如下:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternTest {
    public static void main(String[] args){
        //将一个字符串编译成Pattern对象
        Pattern p=Pattern.compile("a*b");
        // 使用Pattern对象创建Matcher对象
        Matcher m=p.matcher("aaaaab");
        boolean b=m.matches(); 
        //返回true
        System.out.println(b);
    }
}

上面定义的Pattern对象可以多次重复使用。如果某个正则表达式仅需一次使用,则可直接使用Pattern类的静态matches方法,此方法自动把指定字符串编译成匿名的Pattern对象,并执行匹配,如下:

boolean b=Pattern.matches("a*b", "aaaaab");  //返回true

上面语句等效于前面的三条语句。但采用这种语句每次都需要重新编译新的Pattern对象,不能重复利用已编译的Pattern对象,所以效率不高。
Pattern是不可变类,可供多个并发线程安全使用。
Matcher类提供了如下几个常用方法。

  • find():返回目标字符串中是否包含与Pattern匹配的子串。
  • group():返回上一次与Pattern匹配的子串。
  • start():返回上一次与Pattern匹配的子串在目标字符串中的开始位置。
  • end():返回上一次与Pattern匹配的子串在目标字符串中的结束位置加1。
  • lookingAt():返回目标字符串前面部分与Pattern是否匹配。
  • matches():返回整个目标字符串与Pattern是否匹配。
  • reset(),将现有的Matcher对象应用于一个新的字符序列。

在Pattern、Matcher类的介绍中经常会看到一个CharSequence接口,该接口代表一个字符序列,其中CharBuffer、String、StringBuffer、StringBuilder都是它的实现类。简单地说,CharSequence代表一个各种表示形式的字符串。

通过Matcher类的find()和group()方法可以从目标字符串中依次取出特定子串(匹配正则表达式的子串),下面的例子程序示范了这种用途:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FindGroup {
    public static void main(String[] args){
        //创建一个Pattern对象,并用它建立一个Matcher对象
        Matcher m= Pattern.compile("\\w+").matcher("Java is very easy!");
        while (m.find()){
            System.out.println(m.group());
        }
        int i=0;
        while (m.find(i)){
            System.out.println(m.group() + "\t");
            i++;
        }
    }
}

下面是运行结果:

Java
is
very
easy
Java	ava	va	a	is	is	s	very	very	ery	ry	y	easy	easy	asy	sy	y	

从上面运行结果可以看出,find()方法依次查找字符串中与Pattern匹配的子串,一旦找到对应的子串,下次调用find()方法时将接着向下查找。除此之外,find()方法还可以传入一个int类型的参数,带int参数的find()方法从该int索引处向下搜索。
start()和end()方法主要用于确定子串在目标字符串中的位置,如下程序所示:

import java.util.regex.*;

public class StartEnd {
    public static void main(String[] args){
        //创建一个Pattern对象,并用它建立一个Matcher对象
        String regStr="Java is very easy!";
        System.out.println("目标字符串是:" + regStr);
        Matcher m=Pattern.compile("\\w+").matcher(regStr);
        while (m.find()){
            System.out.println(m.group()+"子串的其实位置:"+m.start()+",其结束位置:"+m.end());
        }
    }
}

matcher()和lookingAt()方法有点相似,只是matcher()方法要求整个字符串和Pattern完全匹配时才返回true,而lookingAt()只要字符串以Pattern开头就会返回true。reset()方法可将现有的Matcher对象应用于新的字符序列。看如下例子:

import java.util.regex.*;

public class MatchesTest
{
    public static void main(String[] args)
    {
        String[] mails=
                {
                        "[email protected]" ,
                        "[email protected]",
                        "[email protected]",
                        "[email protected]"
                };
        String mailRegEx="\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";
        Pattern mailPattern=Pattern.compile(mailRegEx);
        Matcher matcher=null;
        for (String mail : mails)
        {
            if (matcher==null)
            {
                matcher=mailPattern.matcher(mail);
            }
            else
            {
                matcher.reset(mail);
            }
            String result=mail + (matcher.matches() ? "是" : "不是")
                    + "一个有效的邮件地址!";
            System.out.println(result);
        }
    }
}

上面程序创建了一个邮件地址的Pattern,接着用这个Pattern与多个邮件地址进行匹配。当程序中的Matcher为null时,程序调用matcher()方法来创建一个Matcher对象,一旦Matcher对象被创建,程序就调用Matcher的reset()方法将该Matcher应用于新的字符序列。
事实上,String类里也提供了matches()方法,该方法返回该字符串是否匹配指定的正则表达式。例如:

"[email protected]".matches("\\w{3,20}@\\w+\\.(com|org|cn|net|gov)")
//返回true

除此之外,还可以利用正则表达式进行对目标字符串的分割、查找、替换等操作,看如下例子:

import java.util.regex.*;

public class ReplaceTest {
    public static void main(String[] args)
    {
        String[] msgs=
                {
                        "Java has regular expressions in 1.4",
                        "regular expressions now expressing in Java",
                        "Java represses oracular expressions"
                };
        Pattern p=Pattern.compile("re\\w*");
        Matcher matcher=null;
        for (int i=0 ; i < msgs.length ; i++)
        {
            if (matcher==null)
            {
                matcher=p.matcher(msgs[i]);
            }
            else
            {
                matcher.reset(msgs[i]);
            }
            System.out.println(matcher.replaceAll("哈哈:)"));
            System.out.println(matcher.replaceFirst("666"));
        }
    }
}

还可以用来查找,例如邮编等:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FindZipCode {
    public static Pattern ZIP_CODE_PATTERN = Pattern.compile("(?<![0-9])[0-9]{6}(?![0-9])");
    public static void findZipCode(String text) {
        Matcher matcher = ZIP_CODE_PATTERN.matcher(text);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
    public static void main(String[] args) {
        findZipCode("邮编 100013,电话18612345678");
    }
}

java实例练习

E-mail格式合法性验证与自动修改

如何检验输入的E-mail格式是否合法,这在表单中运用得非常多。我们可以使用正则表达式来实现这一功能,并将其中错误的字符删除以产生合格的E-mail格式。

1.

新建项目checkEmail,并在其中创建一个checkEmail.java文件。在该类的主方法中使用Mather语句调用Pattern类的matcher()方法生成一个Matcher对象m,最后通过m.appendReplacement()方法实现自动修改功:

package chechEmail;

import java.util.regex.*;

public class chechEmail {
    public static void main(String[] args){
        String str="apple:[email protected]";
        Pattern p=Pattern.compile("^\\.|^\\@");  //检测输入的Email地址是否以非法符号"."或"@"开头
        Matcher m=p.matcher(str);
        if (m.find()){
            System.out.println("EMAIL地址不能以'.'或'@'作为起始字符");
        }
        p = Pattern.compile("^www\\.");        // 检测是否以“www.”为起始
        m = p.matcher(str);
        if (m.find()) {
            System.out.println("EMAIL地址不能以'www.'起始");
        }
        p = Pattern.compile("[^A-Za-z0-9\\.\\@_\\-~#]+");// 检测是否包含非法字符
        m = p.matcher(str);
        StringBuffer sb = new StringBuffer();
        boolean result = m.find();
        boolean deletedIllegalChars = false;
        while (result) {
            deletedIllegalChars = true;        // 如果找到了非法字符那么就设下标记
            // 如果里面包含非法字符如冒号双引号等,那么就把他们消去,加到SB里面
            m.appendReplacement(sb, "");
            result = m.find();
        } m.appendTail(sb);
        String str1 = sb.toString();
        if (deletedIllegalChars) {
            System.out.println("输入的EMAIL地址里包含有冒号、逗号等非法字符,请修改");
            System.out.println("您现在的输入为: " + str);
            System.out.println("修改后合法的地址应类似: " + str1);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/tonydz0523/article/details/86656227