黑马程序员_Java基础_正则表达式_25

来源:互联网 发布:淘宝优惠券转化淘宝客 编辑:程序博客网 时间:2024/05/21 19:35

                                                  ------- android培训、java培训、期待与您交流!----------

 

导读:正则表达式-特点、匹配、切割、替换,获取,网络编程-网页爬虫

 

1、正则表达式(特点、匹配、切割、替换)

  • String包中的操作字符串的方法,操作起来,一、太简单,二、组合起来操作复杂数据代码过多。对于字符串进行操作即简单,又快捷的方式就是正则表达式。
  • 正则表达式是用一堆符号来表示一堆代码。最终用的还是操作字符串的一些最常用的方法。Web技术中自定义的一些标签就是这样,这个标签就对应了一个Java类(用符号来代表一些代码的数据)。
  • 正则表达式是java.util.regex中的类Pattern

/*

  • 正则表达式:符合一定规则的表达式。

       作用:用于专门操作字符串。

       特点:用于一些特定的符号来表示一些代码操作。这样就简化书写。

       所以学习正则表达式,就是在学习一些特殊符号的使用。

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

       弊端:符号定义越多,正则越长,阅读性越差。

  • 具体操作功能:

1,匹配:booleanmatches(String regex)方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。(带有String regex的就是要匹配正则表达式。)

2,切割:Stringsplit();

3,替换:StringreplaceAll(regex,str);如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。

*/

  • 组虽然作用起来比较简单,但是书写起来,阅读性极差。

在表达式 ((A)(B(C))) 中,存在四个这样的组:(看有几个左括号就封装成几个组)

1    ((A)(B(C)))

2    \A

3    (B(C))

4    (C)

  • 当要替换复杂的字符串的时候,这个时候就要用到正则表达式。
  • 在替换的过程中,我们可以通过另外的一个符号来获取前面规则中的一个组。如,用“$1”。表示前面规则中的第一个组。如果不写1发生字符串越界,因为他认为整个字符串就是一个组,即第0组。如果定义了一个()那么他就是从第1组开始编。
  • class RegexDemo

{

       publicstatic void main(String[] args)

       {

              //demo();

              //System.out.println((char)11);

              //checkTel();

              //splitDemo("zhangsan.lisi.wangwu","\\."); //用点来分隔时的写法

              //splitDemo("c:\\abc\\a.txt","\\\\"); //两个反斜杠的写法。

              //splitDemo("erkktyqqquizzzzzo","(.)\\1+");

//按照叠词完成切割。为了可以让规则的结果被重用

//可以将规则封装成一个组。用()完成。组的出现都有编号。

//从1开始。 想要使用已有的组可以通过  \n(n就是组的编号)的形式来获取。

              String str ="wer1389980000ty1234564uiod234345675f";//将字符串中的数组替换成#。

              //replaceAllDemo(str,"\\d{5,}","#"); //数字如果超过5个的就把你替换为#

              Stringstr1 = "erkktyqqquizzzzzo";//将叠词替换成$.  //将重叠的字符替换成单个字母。zzzz->z

              replaceAllDemo(str1,"(.)\\1+","$1");

       }

       publicstatic void replaceAllDemo(String str,String reg,String newStr)

       {

              str= str.replaceAll(reg,newStr);

              System.out.println(str);

       }

       //正则表达式中有很多的符号,点就是一个特殊的符号,它代表任意字符。所以不能和点来直接的切东西。如果非要用点来切的话,可以转义一下。用“\\.”l因为在正则表达式中“\.”是一个整体,代表正则表达式中普通的一点。如果放在字符串中,还要把\给转义一下。

public static void splitDemo(String str,String reg)

       {

              //Stringreg = " +";//按照多个空格来进行切割(空格出现了一次或者多次)

              String[]arr = str.split(reg); 

              System.out.println(arr.length);

              for(Strings : arr)

              {

                     System.out.println(s);

              }

       }

       /*

       匹配

       手机号段只有 13xxx 15xxx 18xxxx

       */

       publicstatic void checkTel()

       {

              Stringtel = "16900001111";

              StringtelReg = "1[358]\\d{9}";

              System.out.println(tel.matches(telReg));

       }

       publicstatic void demo()

       {

              Stringstr = "b23a23456789";

              Stringreg = "[a-zA-Z]\\d*";

              booleanb= str.matches(reg);

              System.out.println(b);

       }

       publicstatic void checkQQ()

       {

              Stringqq = "123a454";

              Stringregex = "[1-9]\\d{4,14}"; //等同于下面的语句。

              //Stringregex = "[1-9][1-9]{4,14}"; //第一个字符中1到9中的一个,第二个字符是1到9中的一个,并且循环4到14次。

              booleanflag = qq.matches(regex);

              if(flag)

                     System.out.println(qq+"...isok");

              else

                     System.out.println(qq+"...不合法");

       }

       /*

       对QQ号码进行校验

       要求:5~15  0不能开头,只能是数字

       这种方式,使用了String类中的方法,进行组合完成了需求。但是代码过于复杂。

       */

       publicstatic void checkQQ_1()

       {

              Stringqq = "1882345a0";

              intlen = qq.length();

              if(len>=5&& len<=15)

              {

                     if(!qq.startsWith("0"))//Integer.parseInt("12a");NumberFormatException

                     {

                            try

                            {

                                   longl = Long.parseLong(qq); 

//可以用parseInt来判断是否有非法的,位数最多有15位因此,可以用parseLong();

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

                            }

                            catch(NumberFormatException e)

                            {

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

                            }

                            /*

                            char[]arr = qq.toCharArray();//123a4

                            booleanflag = true;

                            for(intx=0;x<arr.length; x++)

                            {

                                   if(!(arr[x]>='0'&& arr[x]<='9'))

                                   {

                                          flag= false;

                                          break;

                                   }

                            }

                            if(flag)

                            {

                                   System.out.println("qq:"+qq);

                            }

                            else

                            {

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

                            }

                            */

                     }

                     else

                     {

                            System.out.println("不可以0开头");

 

                     }

              }

              else

              {

                     System.out.println("长度错误");

              }

       }

}

  • 部分常用正则表达式

Ø 字符

x 字符 x

\\ 反斜线字符

\0n 带有八进制值 0 的字符 n (0 <= n <= 7)

\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)

\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)

\xhh 带有十六进制值 0x 的字符 hh

\uhhhh 带有十六进制值 0x 的字符 hhhh

\t 制表符('\u0009')

\n 新行(换行)符('\u000A')

\r 回车符('\u000D')

\f 换页符('\u000C')

\a 报警 (bell) 符 ('\u0007')

\e 转义符('\u001B')

\cx 对应于 x 的控制符

Ø 字符类

[abc] a、b 或 c(简单类)(可以用来判断字符串中某一个字符位上出现的字符,要么是a要么是b要么是c)

[^abc] 任何字符,除了 a、b 或 c(否定)

[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)

[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)

[a-z&&[def]] d、e 或 f(交集)

[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)

[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)

Ø 预定义字符类

. 任何字符(与行结束符可能匹配也可能不匹配)

\d 数字:[0-9]  (\和d加在一块才代表0到9,在编程的时候要写为\\d)

\D 非数字: [^0-9]

\s 空白字符:[\t\n\x0B\f\r]

\S 非空白字符:[^\s]

\w 单词字符:[a-zA-Z_0-9] (起邮箱名,字母数字划线)

\W 非单词字符:[^\w]

Ø Greedy 数量词

X?    X,一次或一次也没有

X*    X,零次或多次

X+    X,一次或多次

X{n}   X,恰好 n 次

X{n,}  X,至少 n 次

X{n,m}  X,至少 n 次,但是不超过 m 次

Ø 边界匹配器

^    行的开头

$    行的结尾

\b    单词边界

\B    非单词边界

\A    输入的开头

\G    上一个匹配的结尾

\Z    输入的结尾,仅用于最后的结束符(如果有的话)

\z    输入的结尾

 

2、正则表达式(获取)

  • 匹配、切割、替换这三个只能按照规则操作一些字符串,而我现在想把符合规则的子串取出来。以前取子串用subString来取,如果想取描写位置的字符串的话,可以用indexOf()来取。

/*

  • 正则表达式的第四个功能。

4,获取:将字符串中的符合规则的子串取出。

Ø 操作步骤:

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

2,让正则对象和要操作的字符串相关联。

3,关联后,获取正则匹配引擎。

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

*/

  • java.util.regex中的类Pattern,正则表达式的编译表示形式。这个类没有构造方法,不能new对象,所以它中的方法都是静态的方法(无对象持有的特有数据),返回的是静态的对象。
  • 方法:

Ø static Pattern compile(String regex):将给定的正则表达式编译到模式中。(将正则传进来,返回一个Pattern的对象)

Ø Matcher matcher(CharSequence input):创建匹配给定输入与此模式的匹配器。(返回此模式的新匹配器)

  • java.util.regex中的类Matcher,可以通过解释Pattern 对 character sequence 执行匹配操作的引擎。(我们称之为匹配器,或者称之为引擎)
  • 方法:

Ø boolean matches():尝试将整个区域与模式匹配。(String对象中的matcher(),就是通过Pattern和Matcher两个对象来完成的。)

Ø String replaceAll(String replacement):替换模式与给定替换字符串相匹配的输入序列的每个子序列。(String类中的String replaceAll(Stringreplacement),用的就是它)

Ø boolean find():尝试查找与该模式匹配的输入序列的下一个子序列。(从现在指针的位置身后查找)

Ø String group():返回由以前匹配操作所匹配的输入子序列。(获取匹配后的结果)

Ø int start():返回以前匹配的初始索引。

Ø lnt end():返回最后匹配字符之后的偏移量。

  • import java.util.regex.*;

class RegexDemo2

{

       publicstatic void main(String[] args)

       {

              getDemo();

       }

       publicstatic void getDemo()

       {

              Stringstr = "ming tian jiu yao fang jia le ,da jia。";

              System.out.println(str);

              String reg = "\\b[a-z]{4}\\b"; //找到三个字母后,还要进行单词的匹配“\b”

              //将规则封装成对象。

              Patternp = Pattern.compile(reg);

              //让正则对象和要作用的字符串相关联。获取匹配器对象。

              Matcherm  = p.matcher(str);

              //System.out.println(m.matches());

//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。只不过被String的方法封装后,用起来较为简单。但是功能却单一。

              //booleanb = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。

              //System.out.println(b);

              //System.out.println(m.group());//用于获取匹配后结果。

              //System.out.println("matches:"+m.matches()); //一个匹配器,对于对于应一个指针。如果这里进行匹配,则将整个的str和规则进行匹配,返回的是false,这个时候指针还要向下走,接着循环的匹配。

              while(m.find()) //(取出方式用这个来完成)类似于迭代器,用循环。你只有去找,去匹配了才能去取。你不找,不把规则作用在字符串上,你是找不了的。

              {

                     System.out.println(m.group());

                     System.out.println(m.start()+"...."+m.end());//获取子串的索引位置(含对不含尾)

              }

       }

}

 

3、练习

  • import java.util.*;

class RegexTest

{

       publicstatic void main(String[] args)

       {

//            test_1();

//            ipSort();

              checkMail();

       }

       /*

       需求:对邮件地址进行校验。

       */

       publicstatic void checkMail()

       {

              Stringmail = "abc12@sina.com";

              mail= "1@1.1";

              Stringreg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配。

              reg= "\\w+@\\w+(\\.\\w+)+";//相对不太精确的匹配。

              //mail.indexOf("@")!=-1 //这样匹配的方式不要用。

              System.out.println(mail.matches(reg));

       }

       /*

       需求:

       将下列字符串转成:我要学编程.

       到底用四种功能中的哪一个呢?或者哪几个呢?

       思路方式:

       1,如果只想知道该字符是否对是错,使用匹配。

       2,想要将已有的字符串变成另一个字符串,替换。

       3,想要按照自定的方式将字符串变成多个字符串。切割。获取规则以外的子串。

       4,想要拿到符合需求的字符串子串,获取。获取符合规则的子串。

       */

       publicstatic void test_1()

       {

              Stringstr = "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程";

              /*

              将已有字符串变成另一个字符串。使用 替换功能。

              1,可以先将 . 去掉。

              2,在将多个重复的内容变成单个内容。

              */

              str =str.replaceAll("\\.+","");

              System.out.println(str);

              str= str.replaceAll("(.)\\1+","$1");

              System.out.println(str);

       }

       /*

       192.68.1.254102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30

       将ip地址进行地址段顺序的排序。

       还按照字符串自然顺序,只要让它们每一段都是3位即可。

       1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。

       2,将每一段只保留3位。这样,所有的ip地址都是每一段3位。

       */

       publicstatic void ipSort()

       {

              Stringip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";

              ip= ip.replaceAll("(\\d+)","00$1"); //每一个段至少是一位。将每一个段补最多的2个0;

              System.out.println(ip);

              ip= ip.replaceAll("0*(\\d{3})","$1"); //获取每段中,补0后的后三位

              System.out.println(ip);

              String[]arr = ip.split(" ");

              TreeSet<String>ts = new TreeSet<String>();

              for(Strings : arr)

              {

                     ts.add(s);

              }

              for(Strings : ts)

              {

                     System.out.println(s.replaceAll("0*(\\d+)","$1")); //将补的0省去不写。

              }

       }

}

  • 想注册我的论坛,到邮箱里去点激活链接去,你要是地址写错了,邮件就发错了,你收不到邮件,我的论坛你就登不上去,确保会员邮箱是正确的,因为我要给他发一些广告。

 

3、网络编程(网页爬虫)

/*

网页爬虫(蜘蛛)

*/

import java.io.*;

import java.util.regex.*;

import java.net.*;

import java.util.*;

class RegexTest2

{

       publicstatic void main(String[] args) throws Exception

       {

              getMails_1();

       }

       publicstatic void getMails_1()throws Exception

       {

              URLurl = new URL("http://192.168.1.254:8080/myweb/mail.html");

              URLConnectionconn = url.openConnection();

              BufferedReaderbufIn = new BufferedReader(new InputStreamReader(conn.getInputStream()));

              Stringline = null;

              Stringmailreg = "\\w+@\\w+(\\.\\w+)+";

              Patternp = Pattern.compile(mailreg);

              while((line=bufIn.readLine())!=null)

              {

                     Matcherm = p.matcher(line);

                     while(m.find())

                     {

                            System.out.println(m.group());

                     }

              }

       }

       /*

       获取指定文档中的邮件地址。

       使用获取功能。Pattern  Matcher

       */

       publicstatic void getMails()throws Exception

       {

              BufferedReaderbufr =

                     newBufferedReader(new FileReader("mail.txt"));

              Stringline = null;

              Stringmailreg = "\\w+@\\w+(\\.\\w+)+";

              Patternp = Pattern.compile(mailreg);

              while((line=bufr.readLine())!=null)

              {

                     Matcherm = p.matcher(line);

                     while(m.find())

                     {

                            System.out.println(m.group());

                     }

              }

       }

}

  • 早期的时候是算邮箱,用随机的方式或者用顺序的方式产生,计数器。写邮件程序,往这一批邮箱里面发指定的广告页面。但是这一批邮箱里面可能只有几个是注册过的,剩下有很多都是没有注册过的。中奖率不高。那么从互联网上获取一批已经存在的邮件不就可以了吗。怎么获取?搞一个爬虫过去,把网页获取到了之后,把这里面的数据一行一行的去扫,把凡是符合邮箱的规则的一段数据,全取过来。
  • 百度的程序都是自动的,散发出n个蜘蛛在互联网上开始爬,把最新的网页博客都爬过来,只要爬完了之后,你只要搜都能搜到,都在百度的服务器上呢。现在还爬关键字。以前爬网头的关键字,现在还爬网页主体数据的关键字。
  • 在以后学JavaWeb的时候会学到一个JavaMail,用java来写一个邮件收发程序。完全可以用你写的程序给新浪,搜狐发邮件。自己写一个邮件服务器,再把邮件地址读出来以后,发垃圾邮件就OK了。


                                                    ------- android培训、java培训、期待与您交流!----------  

 

0 0
原创粉丝点击