黑马程序员_Java基础_正则表达式,校验QQ号,手机号,邮箱,IP地址排序,网络爬虫

来源:互联网 发布:mysql primarykey 编辑:程序博客网 时间:2024/05/02 23:19
一,正则表达式

概述:符合一定规则的表达式。用于专门用于操作字符串的。虽然字符串中有很多字符串的操作方法,但是使用起来比较繁琐,而且代码量比较多。

特点:用一些特定的符号表示以一些代码操作,简化书写,学习正则表达式就是学习一些特殊符号的使用。

好处:可以简化对字符串的复杂操作。

 

拿一个简单的例子比较说明:比如需要编写一个程序验证QQ号是否正确,首先QQ号必须是515位的,第一位19开头,后面可以使任意的数字。

使用传统操作字符串的方法:判断字符串长度是不是515,不满足则提示错误,满足在判断第一位是不是19,不满足提示错误,满足在循环遍历第二位以后字符是不是09的数字,不是则推出提示错误,满足则打印该QQ号。


class QQCheckDemo{    public static void main(String[] args) {        String QQ = "75332414";        if(QQ.length()>=5 && QQ.length()<=15)        {            if (!(QQ.startsWith("0")))            {                char[] arr = QQ.toCharArray();                boolean flag = true;                for (int i=0;i<QQ.length() ;i++ )                {                    //System.out.println(arr[i]);                    if(!(arr[i]>='0' && arr[i]<='9'))                    {                        flag = false;                        System.out.println("出现非法字符");                        break;                    }                }                if (flag)                {                    System.out.println(QQ);                }                        }            else                System.out.println("首位不能为0");        }        else            System.out.println("QQ位数出错");    }}

分析发现以上代码还可以简化,当字符串长度满足后,可以通过将字符串转换成长整型的数,就可以省去判断第一位和遍历判断第二位以后是不是数字的情况了。

代码:

    try

    {

        Long l = Long.parseLong(QQ);

        System.out.println("QQ:" + l);

    }

    catch (Exception e)

    {

        System.out.println("出现非法字符");

    }

 

二,但是尽管这样做还是很麻烦,正则表达式则提供了更简便的判断字符串是否符合我们的要求。下面使用正则表达式判断QQ号是否符合要求。


Class QQCheck {    public static void main(String[] args) {        String qq = "534312354";        String regex = "[1-9][0-9]{4,14}";        //regex就是正则表达式的意思,在定义一个规则,第一位是1-9之间的数,从第二位开始是0-9之间的数,一共4到14个,少于4个和多于14都不行        boolean flag = qq.matches(regex);        if (flag)        {            System.out.println("QQ号是:"qq);        }        else            System.out.println("qq错误,请检查");    } }

三,正则表达式常见操作分类

1,匹配:

匹配就是判断某个字符串是否符合规定的要求,比如上面判断QQ号是不是符合要求,就属于匹配。匹配返回的结果是true或者false

使用的方法:String类的 public boolean matches(String regex)

regex就是正则表达式,判断给定字符串是否符合该表达式。

 

需求:判断用户输入的手机号是不是符合要求。手机号格式13*********15*********18********

分析:手机号第一位是1开头,第二位只能是358,后面全部是数字,手机号是11为数的。

    String  tel = 13854745658;

    String regex = 1[358]\\d{9};  //其中\d代表的是09的数字,也可以写成[0-9],因为windows下的反斜杠会被转义,所以在加一个反斜杠。

    boolean b = tel.matches(regex);

匹配过程:返回的结果是true,过程是:先判断tel的第一个字符是1,判断第二个是不是358,是3,正确,所以判断第三位,是数字,在判断第四个是数字,在判断第五个是数字......如果任意一个不满足,则不再判断下一位,返回错误。

 

2,切割:

使用指定的正则表达式拆分给定的字符串,使用的方法是String类的split()方法

public String[] split(String regex)

注意:字符串拆分后返回的是一个字符串数组。


public class Demo{    public static void main(String[] args) {        String str = "dsfghdfjk*dshgkj*hbj*";        String[] ss = str.split("\\*");     //需要使用两次转义字符        for(String s : ss) {            System.out.println(s);        }    }}

举例:

(1)字符串:s = D:\\abc\\def\\t.txt,切割得到文件夹及目录。

String[] strs = s.split(\\\\);使用两个反斜杠作为转义字符。

 

(2)字符串:s = sgjh    sajgdskjg   sdaghu  e;

需要按照多个空格进行对字符串的拆分,正则表达式为:String regex =  +

一个空格加上一个+号表示,一个或多个空格。

 

3)字符串:s = fgsdkkksdgdfiiigsdfhhsagdfkhghll,按照叠词进行对字符串的切割。

多个空格需要用到组的概念,正则表达式:String regex= (.)\\1+

()就是组,可以让规则的结果被重用,点代表的是任意字符,组的出现都有编号,标号是从1开始的,使用已有的组可以通过 \nn是组号)获取。

该表达式的获取过程是:判断第一个字符是不是字符,是,判断第二个是不是字符,是,判断是不是和第一个相等,是在判断第三个是不是和第二个相等,不是则从这个位置分割一次,在判断第四个......

 

3,替换:

替换是通过String类的replaceAll()方法。

public String replaceAll(String regex,String s)

将字符串的所有匹配regex的字符串替换成s

 

需求:将字符串的超过3位的数字全部替换成#号。


public class Demo2{    public static void main(String[] args) {        String str = "agsdf1535dsh453432653dfshg3546";//正则表达式:\d代表0到9之间的数字,{3,}代表数字出现三次或三次以上        String regex = "\\d{3,}"";        str = str.replaceAll(regex,"#");        System.out.println(str);    }}

举例:

给定的字符串中有叠词,现在要将重叠的字符替换成一个该字符。

String s = asdgdddsdggsagggrrryrtusdfgfd;

String regex = (.)\\1+;

s = s.replaceAll(regex,$1);

$是一个特殊符号,如果想将多个连续相同字符替换成指定该连续字符就要使用$符号。

 

4,获取。

 

四,正则表达式的获取

获取比较特殊,和匹配,切割,替换都不同。获取是将字符串中的复合规则的子串抽取出来。

步骤:

1,将正则表达式封装成对象。

2,让正则表达式和要操作的字符串关联。

3,关联后获取正则表达式的匹配引擎。

4,通过引擎对复合规则的子串进行操作,比如取出。

方法是首先获得Pattern类的对象,因为正则表达式必须首先被编译成此类的实例,然后通过Matcher类的matcher方法创建匹配器,Matcher对象可以与任意的字符串串序列匹配。

Pattern类没有构造函数,所以要通过静态方法获取该类对象。调用顺序是:

 Pattern p = Pattern.compile("a*b");

 Matcher m = p.matcher("aaaaab");

 boolean b = m.matches();

 

其实String类的matchs方法,底层使用的就是Pattern类和Matcher类对象来完成的,只不过是String类对其进行了封装,使用起来比较方便,但是有局限性。

 

需求:需求:获取句子中的三个字母的单词,打印出结果。给定句子:nothing is impossible,never give up our dream.


import java.util.regex.*;public class Test1{    public static void main(String[] args) {        String str = " nothing is impossible,never give up our dream abc.";        String reg = "\\b[a-z]{3}\\b";        //将正则表达式封装成对象        Pattern p = Pattern.compile(reg);        //将正则表达式与要操作的字符串关联,获取匹配器        Matcher m = p.matcher(str);                //将规则作用在字符串        //boolean b = m.find();//这里find是查找三位字母的单词,直到找到第一个为止        //System.out.println(m.group());//获取匹配后的结果        //要想全部找到必须使用循环,可以将find方法看做是一个迭代器。        while(m.find()) {            System.out.println(m.group());        }    }}

正则表达式:String reg = "\\b[a-z]{3}\\b";的含义是:az的字母出现三次,\b表示的是单词的边界,两边是边界。

 

五,正则表达式的几个练习

正则表达式在的解题思路是:

(1)如果只想知道该字符串是对或错,使用匹配。matches()

(2)如果要将字符串按照给定的规则进行拆分成多个子串,使用切割。split()

(3)如果要将已有的字符串变成另一个,则使用替换。replaceAll()

(4)要拿到符合要求的子串,使用获取。

 

 

1,练习一:校验邮箱是否正确。

 

分析:邮箱格式必须要有@符号,@左边是字母数字的组合,位数字520位之间,@右边挨着@的部分是字母或数字的组合(可以使纯数字或字母),它后面是.com.cn.edu之类的字符,所以可以将带点的那一部分封装成组,出现一次或多次。


public class Test1{    public static void main(String[] args) {        String mail = "s334g@qq.com.cn";        mail = "13456@1.n";                //必须有@符号,它左边是数字或字母或数字字母组合,出现5到20次。        //它右边是字母数字或组合,出现一次或多次,它后面是.com之类的。出现一次或多次        String reg = "[a-zA-Z_0-9]{5,20}@[a-zA-Z_0-9]+(\\.[a-zA-Z]+)+";        //不精确的匹配,建议使用上面的正则表达式,比较精确        //reg = "\\w{5,20}@\\w+(\\.\\w+)+";//不同在于最后的部分,可以使数字或字母        if(mail.matches(reg))             System.out.println("邮箱是:" + mail);        else            System.out.println("邮箱格式错误!");    }}

2,练习二:将给定的字符串变成一句正常的话。例如:我我我我我我=====要要要。。。。。进进进..........黑黑黑马马------学学,,,,,,,习习习。。。变成:我要进黑马学习

    代码:


class Test2{    public static void main(String[] args) {        String s = "我我我我我我=====要要要。。。。。进进进..........黑黑黑马马------学学,,,,,,,习习习。。。";                //首先要将中间的符号全部去掉        s = s.replaceAll("\\=","");        s = s.replaceAll("\\。","");        s = s.replaceAll("\\.","");        s = s.replaceAll("\\-","");        s = s.replaceAll("\\,","");        System.out.println(s);        //去掉重复文字        s = s.replaceAll("(.)\\1+","$1");//将出现的任意字符当做第一个组1是组的编号        System.out.println(s);    }}

3,练习三:将IP地址按照地址段顺序进行排序,给定的地址段格式是:

192.168.0.2 185.64.51 192.120.75 27.152.52 64.28.125.0 192.168.5.4

 

分析:1,将每一个ip地址的每一段变成三位,因为最高是三位,如果不这样的话,自然排序会按照第一个数字排序,2.152.5.3就会排到192.168.1.0之后。正确方法应该用002.152.005.003192.168.001.000比较才对。

思路:1,将每位ip的每段前面加两个0,

  2,然后去掉每个ip每段后三位的前面一部分,也就是保证每段是三位数。

  3,将字符串按照空格拆分,得到每个ip,添加到TreeSet集合,因为TreeSet集合有排序功能。


import java.util.*;class Test3{    public static void main(String[] args) {        String ip = "192.168.0.2 185.64.51 192.120.75 27.152.52 64.28.125.0 192.168.5.4";        String reg = "(\\d+)";//找到连续的数字,该规则要重用,所以封装成组        //将每段前面加上2个0        ip = ip.replaceAll(reg,"00$1");//在第一组前面加两个0        //System.out.println(ip);        //值保留每段的后三位        reg = "0*(\\d{3})";//开头是0出现零次或多次,然后是数字出现三次,将数字出现三次封装成组,重用        ip = ip.replaceAll(reg,"$1");//替换成组1,也就是数字出现三次        //System.out.println(ip);        //拆分ip,获得每个ip        String[] str = ip.split(" +");        //将每个ip存储到集合中        TreeSet<String> trees = new TreeSet<>();        for(String s : str) {            trees.add(s);        }                //迭代集合,就是按照大小排序后的结果        for(String st : trees) {            st = st.replaceAll("0*(\\d+)","$1");//第一位是0出现零次或多次,然后是数字,出现最少一次,将数字出现一次或多次封装成组            System.out.println(st);        }    }}

六,综合应用。

需求:编写一个网络爬虫,从一个文本文件中读取所有的邮箱。

 

分析:使用流从一个文本文件中读取每行文本数据,然后获取Pattern对象,每读取一行字符串就获取一次匹配器,寻找该行字符串是不是有符合正则表达式的部分。知道每行字符串都匹配完结束循环。

import java.io.*;import java.util.*;import java.util.regex.*;class Test4{public static void main(String[] args) throws Exception {Scanner in = new Scanner(new FileInputStream("mail.txt"));//邮箱的正则表达式String reg = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]+(\\.[a-zA-Z]+)+";Pattern p = Pattern.compile(reg);//循环匹配每行字符串while(in.hasNextLine()) {String line = in.nextLine();//System.out.println(line);Matcher m = p.matcher(line);while(m.find()) {System.out.println(m.group());}}in.close();}}


如何获取一个网页上的所有邮箱地址呢?只需要将输入流换成网络上的流就可以了。使用URL类获取。


URL url = new URL(“http://127.0.0.1:8080/web/mail.html”);//获取本地主机的Tomcat服务器上的网页。
URLConnection con = url.openConnection();
Scanner in = new Scanner(con.getInputStream());






0 0
原创粉丝点击