java正则表达式学习

1.简单认识正则:      

public class Test {

    public static void main(String[] args) {
        //简单认识正则
        p("abc".matches("..."));
        p("a8729a".replaceAll("\d", "-"));
    }
    
    public static void p(Object o){
        System.out.println(o);
    }

}

一个.代表一个字母

true
a----a

2.简单认识Pattern和Matcher:                

     /**
         * 比下面一句话的好处:
         * 1.Pattern.compile将正则表达式先编译了,速度更快;
         * 2.Pattern 和Matcher有更多的方法,是String.matches所没有的;
         */
        Pattern p = Pattern.compile("[a-z]{3}");
        Matcher m = p.matcher("fgh");
        p(m.matches());
        
        p("fgh".matches("[a-z]{3}"));    //相当于上面三句话

true
true

 解释:

/**
* Pattern:模式,[a-z]{3}的这种模式。
* Matcher:匹配器;[a-z]{3}的这种模式去匹配"fgh"这个字符串;
* 匹配这个字符串的过程之中,要注意有可能产生多个结果,匹配的结果会保留在Matcher对象m里面。
* 这个结果是匹配还是不匹配呢?调用m.matches();
*/

3.初步认识. * + ?                              

        /**
         * 初步认识 . * +
         * . 任意一个字符
         * * 0个或多个
         * + 1个或多个
         * ? 0个或1个,可有可无。
         */
        p("a".matches("."));                                //true
        p("aa".matches("aa"));                                //true
        p("aaaa".matches("a*"));                            //true
        p("aaaa".matches("a+"));                            //true
        p("".matches("a*"));                                //true
        p("aaaa".matches("a?"));                            //false
        p("".matches("a?"));                                //true
        p("a".matches("a?"));                                //true
        p("214523145234532".matches("\d{3,100}"));            //true
        p("192.168.0.aaa".matches("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"));    //false
        p("192".matches("[0-2][0-9][0-9]"));                //true

解释:

.是一个特殊的字符,用转义字符,所以写.       可是在正则表达式里面确实是,但是在java里面比较特殊,用两个\。

所以\.代表.这个字符。

4.范围:

/**
         * 范围
         * []里面匹配一个字符。中括号里面写的再长,也是匹配一个字符
         */
        p("a".matches("[abc]"));
        p("a".matches("[^abc]"));    //取反,除了abc之外的内容
        p("A".matches("[a-zA-Z]"));    //大写字母或小写字母
        p("A".matches("[a-z]|[A-Z]"));    //这种写法和上面写法一样
        p("A".matches("[a-z[A-Z]]"));    //也是a-z或者A-Z的意思
        p("R".matches("[A-Z&&[RFG]]")); //A-Z中的,并且是RFG之一的    

true
false
true
true
true
true

5.认识 s  w   d    

     /**
         * 认识 s  w   d   
         * s     空白字符,包含空格,tab、换行、制表符、回车
         * w     构成单词的字符[a-zA-Z_0-9]
         * 在java里面字符串\代表的是一个反斜线;用正则表达式去匹配一个反斜线: 
         *         正则表达式本身要匹配一个反斜线的话,需要用两个反斜线;
         *         然后你要用字符串把这个正则表达式表现出来的时候,每一个反斜线都要用两个反斜线替代;
         * 在java里面一个反斜线和后面的字符会合在一起,构成一个转义字符;所以在java里面一个反斜线必须用两个反斜线来替代;
         */
        p(" 

	".matches("\s{4}"));
        p(" ".matches("\S"));
        p("a_8".matches("\w{3}"));
        p("abc888&^%".matches("[a-z]{1,3}\d+[&^#%]+"));
        p("\".matches("\\"));
        
        //如果写:p("\".matches("\"))的话:
        //matches("\")里的\会被正则表达式认为成它是一个反斜线;
        //在正则表达式里面,一个也会是一个特殊字符,它会和后面的字符合在一起,那第一个双引号"又没有配对的了;
        //所以要在正则表达式里,匹配一个,要写成:\\

true
false
true
true
true

解释:

/**
* 怎么用正则表达式匹配一个反斜线呢?
* 在java里面 一个必须用两个\来替代。
* 正则表达式本身要匹配一个反斜线,使用\来匹配的,然后你要用字符串把这个正则表达式表现出来的时候,每一个都要用两个\替代;
* 所以要在正则表达式里面匹配一个反斜线,写4个
*/

6.POSIX Style风格:

     //POSIX Style
        //参考API p{Lower}    A lower-case alphabetic character: [a-z]
        p("a".matches("\p{Lower}"));        //true

6.boundary  边界匹配:

     /**
         * boundary 边界匹配
         * ^        位于[]外面,代表开头
         *         一个单词的边界;单词边界:空格、空白字符、各种各样的特殊字符、换行的时候等等,都算单词边界;
         */
        p("hello sir".matches("^h.*"));                        //true
        p("hello sir".matches(".*ir$"));                    //true
        p("hello sir".matches("^h[a-z]{1,3}o\b.*"));        //true
        p("hellosir".matches("^h[a-z]{1,3}o\b.*"));        //false

7.匹配空白行:

     /**
         * white lines空白行:
         */
        //以空白字符开头的并且不是换行符,紧跟0个或多个,以换行符结尾;
        p(" 
".matches("^[\s&&[^\n]]*\n$"));        //true

8.匹配Email地址:

     /**
         * 匹配Email地址的正则表达式
         * 构成单词的字符或者是.-   出现1次或多次     @  单词字符或.- 1次或多次   .  单词字符或.- 1次或多次
         * 注意.是元字符代表任意字符,这里表示.要用 \. 代表
         */
        p("asdfasdfsafsf@dsdfsdf.com".matches("[\w[.-]]+@[\w[.-]]+\.[\w]+"));    //true

.写在[ ]里面表示.          [.-]表示.或者-

例子:

p("ab4com".matches("[a-z]{2}[.]{1}\w{3}"));      ——false,因为要求两个a-z的字母后面紧接的是.   所以false

9.matches()、find()、lookingAt():

     /**
         * matches find  lookingAt
         * matches 是否匹配   matches()永远是匹配整个字符串
         * m.find():     找一个和模式相匹配的子串;是找子串,而不是匹配整个字符串;
         *                   找着一个之后,正则引擎会将找到的子串截掉,然后从剩下的字符串里再找;
         * lookingAt(): 每次找,都是从开头位置找;
         */
        Pattern p = Pattern.compile("\d{3,5}");
        String s = "123-34345-234-00";
        Matcher m = p.matcher(s);
        p(m.matches());                                                //false 
        
        p(m.find());                                                //true
        p(m.find());                                                //true
        p(m.find());                                                //false
        p(m.find());                                                //false
        
        //上面的结果解释:
        //m.matches()运行时,开始分析"123-34345-234-00",分析到123-发现已经不匹配了,停止,返回false;
        //m.find()执行,继续从34345-234-00开始找,find第一个34345返回true;find第二个234返回true,后面两个false
 1 /**
 2          * start():找到的字符串的起始位置;
 3          * end(): 找到的字符串的结束位置;是找到的字符的后面一个位置;
 4          * 必须能够找到,否则打印会报错;
 5          */
 6         Pattern p = Pattern.compile("\d{3,5}");
 7         String s = "123-34345-234-00";
 8         Matcher m = p.matcher(s);
 9         p(m.matches());                                                //false 
10         m.reset();
11         p(m.find());                                                //true
12         p(m.start() + "-" + m.end());                                //0-3
13         
14         p(m.find());                                                //true
15         p(m.start() + "-" + m.end());                                //4-9
16         
17         p(m.find());                                                //true
18         p(m.start() + "-" + m.end());                                //10-13
19         
20         p(m.find());                                                //false
21         
22         p(m.lookingAt());
23         p(m.lookingAt());
24         p(m.lookingAt());
25         p(m.lookingAt());
26         
27         //上面结果解释:
28         //m.matches()执行,分析到123-发现已经不匹配了,停止,返回false;
29         //m.reset()执行,m又回到了"123-34345-234-00"的开头位置。从头开始分析(回到初始的状态);
30         //m.lookingAt():每次从开头位置找,每次找到123,就都返回true

10.replacement:

1 /**
2          * replacement
3          * group():     输出匹配到的子串;整个的正则表达式可以看作组号为0的一个组;
4          */
5         //将下面的字符串中java全都替换成大写的:
6         Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
7         Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava");
8         p(m.replaceAll("JAVA"));

 JAVA JAVA JAVA JAVA IloveJAVA you hateJAVA

 1 //将下面字符串中,找到的java,第奇数个替换成JAVA,第偶数个替换成java
 2         Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
 3         Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf");
 4         StringBuffer buf = new StringBuffer();
 5         int count = 0;
 6         while(m.find()){
 7             count++;
 8             if(count%2 == 0){
 9                 m.appendReplacement(buf, "java");
10             }else{
11                 m.appendReplacement(buf, "JAVA");
12             }
13         }
14         m.appendTail(buf);
15         p(buf);

JAVA java JAVA java IloveJAVA you hatejava afasdfasdf

11.分组:group:

 1         /**
 2          * group 分组
 3          * group():        返回整个正则表达式所匹配的子串;
 4          */
 5         Pattern p = Pattern.compile("\d{3,5}[a-z]{2}");
 6         String s = "123aa-34345bb-234cc-00";
 7         Matcher m = p.matcher(s);
 8         while(m.find()) {
 9             p(m.group());
10         }

123aa
34345bb
234cc

1         //将上面字符串中,匹配的3-5位的数字拿出来:
2         //要知道第几组:数左边的小括号,第一个小括号为第1组,第二个小括号为第2组...
3         Pattern p = Pattern.compile("(\d{3,5})([a-z]{2})");
4         String s = "123aa-34345bb-234cc-00";
5         Matcher m = p.matcher(s);
6         while(m.find()){
7             p(m.group(1));
8         }

123
34345
234

12.抓取网页Email地址的例子:

 1 package com.cy.regexp;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.BufferedWriter;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileReader;
 7 import java.io.FileWriter;
 8 import java.io.IOException;
 9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11 
12 public class EmailSpider {
13 
14     @SuppressWarnings("resource")
15     public static void main(String[] args) {
16         try {
17             BufferedReader br = new BufferedReader(new FileReader("D:\fromEmail.html"));
18             BufferedWriter bw = new BufferedWriter(new FileWriter("D:\findEmail.txt"));
19             
20             String line = "";
21             while((line = br.readLine()) != null){
22                 writeToFile(line, bw);
23             }
24             bw.flush();
25         } catch (FileNotFoundException e) {
26             e.printStackTrace();
27         } catch (IOException e) {
28             e.printStackTrace();
29         }
30     }
31     
32     public static void writeToFile(String line, BufferedWriter bw) throws IOException{
33         Pattern p = Pattern.compile("[\w[.-]]+@[\w[.-]]+\.[\w]+");
34         Matcher m = p.matcher(line);
35         while(m.find()){
36             bw.write(m.group());
37             bw.newLine(); 
38         }
39     }
40 }
View Code

13.修饰符、限定词:

 1         /**
 2          * qulifiers  修饰符 限定词  在数量后面 加限定词
 3          * Greedy quantifiers  贪婪的;默认的写法都是贪婪的;x? x* x+ x{n} x{n,} x{n,m}都是贪婪的
 4          * Reluctant  quantifiers: 勉强的,非贪婪的,和Greedy正好相反:x?? x*? x+? ...
 5          * Possessive quantifiers: 独占的;和贪婪的类似,.{3,10}+,一下吞进去10个字符,不匹配时但是不往外吐,就是找不着;
 6          */
 7 
 8         Pattern p = Pattern.compile(".{3,10}[0-9]");
 9         String s = "aaaa5bbbb6";
10         Matcher m = p.matcher(s);
11         if(m.find()){
12             p(m.start() + "-" + m.end());    //0-10
13         }else{
14             p("not match!");
15         }
16 
17         Pattern p = Pattern.compile(".{3,10}?[0-9]");
18         String s = "aaaa5bbbb6";
19         Matcher m = p.matcher(s);
20         if(m.find()){
21             p(m.start() + "-" + m.end());    //0-5
22         }else{
23             p("not match!");
24         }
25 
26         Pattern p = Pattern.compile(".{3,10}+[0-9]");
27         String s = "aaaa5bbbb6";
28         Matcher m = p.matcher(s);
29         if(m.find()){
30             p(m.start() + "-" + m.end());    
31         }else{
32             p("not match!");            //not match!
33         }
34 
35         Pattern p = Pattern.compile(".{3,10}+[0-9]");
36         String s = "aaaa5bbbb68";
37         Matcher m = p.matcher(s);
38         if(m.find()){
39             p(m.start() + "-" + m.end());    //0-11
40         }else{
41             p("not match!");            
42         }

14.non-capturing groups 非捕获组:

 1         /**
 2          * non-capturing groups
 3          * 非捕获组: 如果符合这个条件就捕获;如果不符合这个条件就不捕获
 4          */
 5         //这个正则表达式匹配 3个字母的后面紧跟的是一个a,像这样的才去匹配它;而且这个a不被抓出来
 6         // ?=a  不捕获这个a
 7         //(?=X)    X, via zero-width positive lookahead   lookahead从头开始看
 8         Pattern p = Pattern.compile(".{3}(?=a)");
 9         String s = "444a66b";
10         Matcher m = p.matcher(s);
11         while(m.find()) {
12             p(m.group());            //444
13         }
14 
15         //前面是a的,3个字母
16         Pattern p = Pattern.compile("(?=a).{3}");
17         String s = "444a66b";
18         Matcher m = p.matcher(s);
19         while(m.find()) {
20             p(m.group());            //a66
21         }
22 
23         //(?!a)  前面不是a的,3个字母
24         Pattern p = Pattern.compile("(?!a).{3}");
25         String s = "444a66b";
26         Matcher m = p.matcher(s);
27         while(m.find()) {
28             p(m.group());    //444 66b
29         }
30 
31         //3个字母, 后面不是a
32         Pattern p = Pattern.compile(".{3}(?!a)");
33         String s = "444a66b";
34         Matcher m = p.matcher(s);
35         while(m.find()) {
36             p(m.group());    //44a  66b
37         }
38 
39         //3个字母,从后往前数,不能是a
40         Pattern p = Pattern.compile(".{3}(?<!a)");
41         String s = "444a66b";
42         Matcher m = p.matcher(s);
43         while(m.find()) {
44             p(m.group());        //444 a66
45         }
46 
47         //3个字母,从后往前数,是a, 包含a
48         Pattern p = Pattern.compile(".{3}(?<=a)");
49         String s = "444a66b";
50         Matcher m = p.matcher(s);
51         while(m.find()) {
52             p(m.group());    //44a
53         }
View Code

15.back refenrences  向前引用:

 1         /**
 2          * back refenrences
 3          * 向前引用;
 4          * (\d\d)匹配两个数字,作为结果;\1 指的是后面的东西必须和前面第一个group找到的结果一模一样
 5          * 第一个group找到的是12,后面是12,和前面第1个group找到的东西一样, 所以返回true
 6          */
 7         Pattern p = Pattern.compile("(\d\d)\1");
 8         String s = "1212";
 9         Matcher m = p.matcher(s);
10         p(m.matches());                //true
11 
12         //第2个group抓到的是2,后面的结果要和第2个group抓到的内容一样
13         Pattern p = Pattern.compile("(\d(\d))\2");
14         String s = "122";
15         Matcher m = p.matcher(s);     //true
16         p(m.matches());    
View Code

16.flags的简写:

 1      /**
 2          * flags的简写
 3          * DOTALL .可以匹配所有的字符,默认的.是不匹配换行符的;
 4          * CASE_INSENSITIVE        忽略大小写
 5          * API:       Case-insensitive matching can also be enabled via the embedded flag expression (?i).
 6          */
 7         Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
 8         
 9         //(?i) 也是非捕获组  跟上面的写法一模一样,上面写法的简写
10         p("Java".matches("(?i)(java)"));    //true
原文地址:https://www.cnblogs.com/tenWood/p/6616894.html