黑马程序员---正则表达式

时间:2023-02-19 15:31:01
-------  android培训 java培训 、期待与您交流! ----------

 

15、正则表达式概述

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

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

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

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

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

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

具体操作功能:

1,匹配:String类中的matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。

2,切割:Stringsplit();

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

15.1Pattern类的表述

java.util.regex 类 Pattern

java.lang.Objectjava.util.regex.Pattern

所有已实现的接口:Serializable

public final class Pattern extends Object implements Serializable

正则表达式的编译表示形式。

指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

因此,典型的调用顺序是

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

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

 boolean b = m.matches();

在仅使用一次正则表达式时,可以方便地通过此类定义matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句

 boolean b =Pattern.matches("a*b", "aaaaab");

等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。

此类的实例是不可变的,可供多个并发线程安全使用。Matcher 类的实例用于此目的则不安全。

15.2正则表达式的构造摘要

构造

匹配

15.2.1字符

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 的控制符

15.2.2字符类

[abc]

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](减去)

15.2.3预定义字符类

.

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

\d

数字:[0-9]“\\表示成对出现”

\D

非数字: [^0-9]

\s

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

\S

非空白字符:[^\s]

\w

单词字符:[a-zA-Z_0-9]

\W

非单词字符:[^\w]

15.2.4POSIX 字符类(仅 US-ASCII)

\p{Lower}

小写字母字符:[a-z]

\p{Upper}

大写字母字符:[A-Z]

\p{ASCII}

所有 ASCII:[\x00-\x7F]

\p{Alpha}

字母字符:[\p{Lower}\p{Upper}]

\p{Digit}

十进制数字:[0-9]

\p{Alnum}

字母数字字符:[\p{Alpha}\p{Digit}]

\p{Punct}

标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

\p{Graph}

可见字符:[\p{Alnum}\p{Punct}]

\p{Print}

可打印字符:[\p{Graph}\x20]

\p{Blank}

空格或制表符:[ \t]

\p{Cntrl}

控制字符:[\x00-\x1F\x7F]

\p{XDigit}

十六进制数字:[0-9a-fA-F]

\p{Space}

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

15.2.5java.lang.Character 类(简单的 java 字符类型

\p{javaLowerCase}

等效于 java.lang.Character.isLowerCase()

\p{javaUpperCase}

等效于 java.lang.Character.isUpperCase()

\p{javaWhitespace}

等效于 java.lang.Character.isWhitespace()

\p{javaMirrored}

等效于 java.lang.Character.isMirrored()

15.2.6Unicode 块和类别的类

\p{InGreek}

Greek 块(简单)中的字符

\p{Lu}

大写字母(简单类别

\p{Sc}

货币符号

\P{InGreek}

所有字符,Greek 块中的除外(否定)

[\p{L}&&[^\p{Lu}]]

所有字母,大写字母除外(减去)

15.2.7边界匹配器

^

行的开头

$

行的结尾

\b

单词边界

\B

非单词边界

\A

输入的开头

\G

上一个匹配的结尾

\Z

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

\z

输入的结尾

15.2.8Greedy 数量词

X?

X,一次或一次也没有使用问号问一下

X*

X,零次或多次

X+

X,一次或多次

X{n}

X,恰好 n 次

X{n,}

X,至少 n 次

X{n,m}

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

15.2.9Reluctant 数量词

X??

X,一次或一次也没有

X*?

X,零次或多次

X+?

X,一次或多次

X{n}?

X,恰好 n 次

X{n,}?

X,至少 n 次

X{n,m}?

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

15.2.10Possessive 数量词

X?+

X,一次或一次也没有

X*+

X,零次或多次

X++

X,一次或多次

X{n}+

X,恰好 n 次

X{n,}+

X,至少 n 次

X{n,m}+

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

15.2.11Logical 运算符

XY

X 后跟 Y

X|Y

X 或 Y

(X)

X,作为捕获组

15.2.12Back 引用

\n

任何匹配的 nth 捕获组

15.2.13引用

\

Nothing,但是引用以下字符

\Q

Nothing,但是引用所有字符,直到 \E

\E

Nothing,但是结束从 \Q 开始的引用

15.2.14特殊构造(非捕获)

(?:X)

X,作为非捕获组

(?idmsux-idmsux)

Nothing,但是将匹配标志i d ms u x on – off

(?idmsux-idmsux:X)

X,作为带有给定标志 i d m s u x on - off的非捕获组

(?=X)

X,通过零宽度的正 lookahead

(?!X)

X,通过零宽度的负 lookahead

(?<=X)

X,通过零宽度的正 lookbehind

(?<!X)

X,通过零宽度的负 lookbehind

(?>X)

X,作为独立的非捕获组

15.3正则表达式代码示例

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个以上含5个

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

               replaceAllDemo(str1,"(.)\\1+","$1");//用美元符号获取前面字符串的组,没有指定数字组,则默认为整个字符串。

        }

public static void replaceAllDemo(String str,Stringreg,String newStr)

        {

               str =str.replaceAll(reg,newStr);

               System.out.println(str);

        }

        publicstatic void splitDemo(String str,String reg)

        {

               //Stringreg = " +";//按照多个空格来进行切割

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

               System.out.println(arr.length);

               for(Strings : arr)

               {

                       System.out.println(s);

               }

        }

        /*

15.4匹配手机号

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

        */

        publicstatic void checkTel()

        {

               Stringtel = "16900001111";

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

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

        }

        publicstatic void demo()

        {

               Stringstr =  “a”;

               Stringstr = "b23a23456789";

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

               Stringreg = "[abc]";//reg中的第一个字符,只能是abc当中的一个,而且此字符串只能有一个字符,

               booleanb= str.matches(reg);

               System.out.println(b);

        }

        publicstatic void checkQQ()

        {

               Stringqq = "123a454";

               Stringregex = "[1-9]\\d{4,14}";

               booleanflag = qq.matches(regex);

               if(flag)

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

               else

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

        }

        /*

        对QQ号码进行校验

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

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

public static 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);

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

                               }

                               catch(NumberFormatException e)

                               {

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

                               }

                               /*使用String类型中的方法组合方法

                               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("长度错误");

               }

        }

}

15.5正则表达式的功能之获取

4,获取:将字符串中的符合规则的子串取出。
 
操作步骤:
1,将正则表达式封装成对象。
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。
4,通过引擎对符合规则的子串进行操作,比如取出。
 
import java.util.regex.*;
 
class RegexDemo2 
{
        public static void main(String[] args) 
        {
               getDemo();
        }
        public static void getDemo()
        {
        String str = "ming tian jiu yao fang jia le ,da jia。";
               System.out.println(str);
               String reg = "\\b[a-z]{4}\\b";
               //将规则封装成对象。
               Pattern p = Pattern.compile(reg);
               //让正则对象和要作用的字符串相关联。获取匹配器对象。
               Matcher m  = p.matcher(str);
               //System.out.println(m.matches());//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。
//只不过被String的方法封装后,用起来较为简单。但是功能却单一。
//             boolean b = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。
//             System.out.println(b);
//             System.out.println(m.group());//用于获取匹配后结果。
               //System.out.println("matches:"+m.matches());此时的matches方法作用于整个字符串,被匹配之后,find继续匹配。
               while(m.find())
               {
                       System.out.println(m.group());
                       System.out.println(m.start()+"...."+m.end());
               }
        }
}
import java.util.*;
class RegexTest 
{
        public static void main(String[] args) 
        {
//             test_1();
//             ipSort();
 
               checkMail();
        }

15.6对邮件地址进行校验

public static void checkMail()
        {
               String mail = "abc12@sina.com";
               mail = "1@1.1";
        String reg = "[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,想要拿到符合需求的字符串子串,获取。获取符合规则的子串。
        */
        将下列字符串转成:我要学编程.
        public static void test_1()
        {
              String str = "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程";
               /*
               将已有字符串变成另一个字符串。使用 替换功能。
               1,可以先将 . 去掉。
               2,在将多个重复的内容变成单个内容。
               */
               str = str.replaceAll("\\.+","");
               System.out.println(str);
               str = str.replaceAll("(.)\\1+","$1");
               System.out.println(str);
        }
        /*
        192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30

15.7将IP地址进行地址段顺序的排序

还按照字符串自然顺序,只要让它们每一段都是3位即可。
1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
2,将每一段只保留3位。这样,所有的ip地址都是每一段3位。
        */
        public static void ipSort()
        {
               String ip = "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");
               System.out.println(ip);
               ip = ip.replaceAll("0*(\\d{3})","$1");
               System.out.println(ip);
               String[] arr = ip.split(" ");
               TreeSet<String> ts = new TreeSet<String>();
               for(String s : arr)
               {
                       ts.add(s);
               }
               for(String s : ts)
               {
        System.out.println(s.replaceAll("0*(\\d+)","$1"));
               }
        }
}

15.8网页爬虫

/*
网页爬虫(蜘蛛)
*/
import java.io.*;
import java.util.regex.*;
import java.net.*;
import java.util.*;
class RegexTest2 
{
        public static void main(String[] args) throws Exception
        {
               getMails_1();
        }
        public static void getMails_1()throws Exception
        {
        URL url = new URL("http://192.168.1.254:8080/myweb/mail.html");
               URLConnection conn = url.openConnection();
               BufferedReader bufIn = new BufferedReader(new InputStreamReader(conn.getInputStream()));
               String line = null;
               String mailreg = "\\w+@\\w+(\\.\\w+)+";
               Pattern p = Pattern.compile(mailreg);
               while((line=bufIn.readLine())!=null)
               {
                       Matcher m = p.matcher(line);
                       while(m.find())
                       {
                               System.out.println(m.group());
                       }
               }
        }
/*
        获取指定文档中的邮件地址。
        使用获取功能。Pattern  Matcher
        */
        public static void getMails()throws Exception
        {
               BufferedReader bufr = 
                       new BufferedReader(new FileReader("mail.txt"));
               String line = null;
               String mailreg = "\\w+@\\w+(\\.\\w+)+";
               Pattern p = Pattern.compile(mailreg);
               while((line=bufr.readLine())!=null)
               {
                       Matcher m = p.matcher(line);
                       while(m.find())
                       {
                               System.out.println(m.group());
                       }
               }
        }
}

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