首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >尚学堂-马士兵-专题-正则表达式

尚学堂-马士兵-专题-正则表达式

作者头像
用户7798898
发布2020-09-27 16:18:06
发布2020-09-27 16:18:06
1.4K0
举报

一、最简单的正则表达式

  • String类的一个方法matches。
代码语言:javascript
复制
package com.string;

public class RegexTest {

    public static void main(String[] args) {
        /*
         * 最简单的正则表达式
         * 这里使用的是String类的matches方法.
         * 这个方法是比较字符是否匹配
         * .表示的时任意一个字符
         */
        System.out.println("abc".matches("..."));
    }
}

正则表达式是处理字符串的。 其实更确切的说,正则表达式是处理字符的。 就拿上面的例子来说, 每一个点代表一个字符。 那么abc是不是三个字符呀?是, 所以满足条件。

  • replaceAll : String一个非常好用的方法
代码语言:javascript
复制
package com.string;

public class RegexTest {

    public static void main(String[] args) {
        /*
         * 最简单的正则表达式
         * 这里使用的是String类的matches方法.
         * 这个方法是比较字符是否匹配
         * .表示的时任意一个字符
         */
        System.out.println("abc".matches("..."));
        /**
         * String的另一个很有用的方法: replaceAll,这个方法有两个参数
         * 第一个参数: regex正则表达式
         * 第二个参数: 替换的字符串
         * 下面这个语句的含义: 替换所有的数组为-
         */
        System.out.println("a43215b".replaceAll("\\d", "-"));
    }
}
代码语言:javascript
复制
运行结果
代码语言:javascript
复制
true
a-----b
代码语言:javascript
复制
String的另一个很有用的方法: replaceAll,这个方法有两个参数。
replaceAll(String regex, String replacement) : 字符串匹配正则表达式, 匹配成功的替换为第二个参数自定的字符串
  • 简单认识pattern和Marcher 上面3句话可以使用下面一句话代替. 但为什么还要用三句话来写呢? * 1. 通过Parrern.compile编译以后, 速度回大幅度提高 * 2. 可以很使用Pattern和Matcher的一些方法
代码语言:javascript
复制
package com.string;

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

public class RegexTest {

    public static void main(String[] args) {
        
        /**
         * 简单认识Pattern 和 Matcher
         */
        //compile:方法, 指的是将一个正则表达式先编译, 这样做的好处是效率提高了.
        //[a-z]:表示的事,a-z任意一个字符
        //{3} 表示的是3个
        Pattern p = Pattern.compile("[a-z]{3}");
        //matcher方法是创建一个输入与匹配模式的匹配器.
        Matcher m = p.matcher("abx");
        //尝试将整个区域与模式进行匹配
        System.out.println(m.matches());
        /*
         * 上面3句话可以使用下面一句话代替. 但为什么还要用三句话来写呢?
         * 1. 通过Parrern.compile编译以后, 速度回大幅度提高
         * 2. 可以很使用Pattern和Matcher的一些方法
         */
        System.out.println("abc".matches("[a-z]{3}"));        
    }
}

二、认识正则表达式

  1. 初识 . * + ? {n} {n,} {n,m}
    • . 代表任意字符
    • * 代表0或者多个
    • + 代表1个或者多个
    • ? 代表0或者1个
    • {n} :代表某一个字符出现指定的次数
    • {n,}: 至少出现某个字符n次
    • {n, m}: 至少n次, 至多m次 运行结果
    代码语言:javascript
    复制
    true
    true
    true
    true
    true
    true
    false
    true
    true
    true
    false
    true
代码语言:javascript
复制
package com.string;

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

public class RegexTest2 {

    public static void main(String[] args) {
        /**
         * 初识 . * + ?
         * . 代表任意字符
         * * 代表0或者多个
         * + 代表1个或者多个
         * ? 代表0或者1个
         * {n} :代表某一个字符出现指定的次数
         * {n,}: 至少出现某个字符n次
         * {n, m}: 至少n次, 至多m次
         */
        System.out.println("aaa".matches("..."));
        System.out.println("a".matches("."));
        System.out.println("aa".matches("aa"));
        System.out.println("aaa".matches("a*"));
        System.out.println("aaa".matches("a+"));
        System.out.println("".matches("a*"));
        System.out.println("aaa".matches("a?"));
        System.out.println("".matches("a?"));
        System.out.println("a".matches("a?"));
        System.out.println("23568745896512".matches("\\d{3,100}"));
        /*
         * \\d表示任意有效字符.
         * . 表示的是常用的.,但是.在正则表达式中有特殊含义(任意字符), 所以需要转义为\. 
         * 而\在正则表达式中也是特殊字符, 所以还需要再加一个\. 因此就是\\.
         * 
         *  下面这个例子是一个简单的ip地址的匹配. 但是如果超出了256怎么办呢?可以再用更详细的方法限定
         */
        System.out.println("192.168.203.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
        //这是一种简单的方法
        System.out.println("192".matches("[0-2][0-9][0-9]"));
        
        
    }
}
  1. 范围 [] 中括号表示范围, 这个范围限定的时一个字符. 上面的案例显示了并集的表示方法, 交集的表示方法.
代码语言:javascript
复制
/**
         * 范围
         * 1. 中括号表示范围
         * 2. 每个范围只对应一个字符, 无论这个范围有多长
         * 3.  
         */
        System.out.println("=========================================");
        //中括号表示范围,abc表示确定范围 
        System.out.println("a".matches("[abc]"));
        //a-z表示一个指定的范围
        System.out.println("a".matches("[a-z]"));
        //表示的时或, a-z或者A-Z,满足一个条件即可
        System.out.println("a".matches("[a-zA-Z]"));
        //或者的另一种表示方法,使用分隔符|
        System.out.println("a".matches("[a-z]|[A-Z]"));
        //或的另一种表示方法
        System.out.println("a".matches("[a-z[A-Z]]"));
        //交集的表示方法
        System.out.println("R".matches("[A-Z&&[Q-Z]]"));
  1. 认识 \s \w \d \
    • \s 表示的时空白字符,包括[ \n\t\f\r\x0B]
    • \S表示的时非空白字符,即[^\s]
    • \w: 表示的是字母字符, 包括[a-zA-Z_0-9]
    • \W: 表示的是非字母字符, 即[^\w]
    • \d: 表示的是数字,范围[0-9]
    • \D: 表示的时非数字, 即[^0-9] 或者 [^\d]
    • \ 在正则表达式中使用四个\表示. 即\\\\. 下面的例子说了为什么这样表示. java中的\使用的是两个\, 即\\
代码语言:javascript
复制
       /**
         * 认识 \s \w \d \
         * \s: 代表空白字符 :[ \t\n\x0B\f\r]
         * \S: 代表非空白字符, 除了空白字符以外的字符  [^\s]
         * \w: 单词字符 [a-zA-Z_0-9]
         * \W: 非单词字符 [^\w]
         * 
         * \d: 表示的时数字[0-9]
         * \D: 表示的时非数字[^\d]或者[^0-9]
         */
        System.out.println("============================");
        /*
         * \s表示的时空白字符[ \n\t\x08\f\r]. 在正则表达式中, \s本身代表的是空白字符. 由于\有特殊的含义,
         * 所以, 在写\s的时候, 需要写成\\s.
         * 下面这句话是匹配4个空白字符 - true
         */
        System.out.println(" \n\t\r".matches("\\s{4}"));
        //\S表示的时非空白字符, 空格是空白字符, 所以返回false
        System.out.println(" ".matches("\\S"));
        //\\w匹配的是单词字符, 单词字符的范围是[a-zA-Z_0-9], 所以返回的时-true
        System.out.println("a_8".matches("\\w{1,3}"));
        /*
         * 下面这句话的含义
         * [a-z]{0,3}表示0-3个字符
         * \\d+:表示的是1个或多个数字
         * [&^%$]+: 表示的时中括号中的一个或者多个
         */
        System.out.println("abc888&^%".matches("[a-z]{0,3}\\d+[&^%#]+"));
        /*
         * 下面说说\本身
         * 正则表达式如何表示斜杠呢. 比如我有一个反斜杠, 如何匹配?
         * 
         * 首先在java中, \是有特殊含义的. 比如\"表示的是一个". 如果想表示字符串类型的\, 不能直接使用"\",因为后一个双引号会被转义.
         * 因此在java中,想要表示\,需要使用\\
         * 
         * 在正则表达式中, \有特殊的含义, 比如\s \d \w. 因此表示\需要使用\\. 然后\\表示的是一个\, 和后面的"会发生转义. 
         * 我们采取的方式是对这两个反斜杠都进行转义, 所以就是\\\\.
         * 
         */
        System.out.println("\\".matches("\\\\"));
        
  1. 正则表达式的边界处理
    • ^ : 行的开头
    • $行的几位
    • \b单词边界
    • \B非单词边界 练习: 单词边界
代码语言:javascript
复制
/**
         * 边界字符
         * ^: 行的开头
         * $: 行的结尾
         * \b: 单词边界
         * \B: 非单词边界
         */
        System.out.println("===============================");
        /*
         * ^表示的是行的开头. 写在一行的最前面
         * 表示以a开头,后面跟着1个或者多个字符
         */
        System.out.println("abc".matches("^a.*"));
        /*
         * $表示行的结尾. 如果$出现在最后, 则表示这一行已经结尾了.
         * 下面的正则表达式表示, 以任意字符结尾
         */
        System.out.println("def".matches(".*$"));
        //以h开头
        System.out.println("hello sir".matches("^h.*"));
        //以ir结尾
        System.out.println("hello sir".matches(".*ir$"));
        /*
         * 下面这个语句的含义
         * ^h: 以h开头
         * \\w{0,3}: h后面跟着0-3个单词字符
         * o: 后面跟着一个o
         * \b: 表示的是单词的结尾. 
         * .*: 表示1个或多个字符
         * ir$: 以ir结尾
         */
        System.out.println("hello sir".matches("^h\\w{0,3}o\\b.*ir$"));
        /*
         * 下面这个案例返回false, 和上面的区别是, 单词hello, o不是单词的结尾
         */
        System.out.println("hellosir".matches("^h\\w{0,3}o\\b.*ir$"));
        
        /*
         * 如何匹配带有空格的空白行. 空白行虽然没有字符, 但是这一行可能有空白字符, 如空格等.
         * java中,换行用\n表示
         * 
         */
        System.out.println(" \n".matches("^[\\s&&[^\\n]]*\\n$"));
代码语言:javascript
复制
/**
         * 边界字符
         * ^: 行的开头
         * $: 行的结尾
         * \b: 单词边界
         * \B: 非单词边界
         */
        System.out.println("===============================");
        /*
         * ^表示的是行的开头. 写在一行的最前面
         * 表示以a开头,后面跟着1个或者多个字符
         */
        System.out.println("abc".matches("^a.*"));
        /*
         * $表示行的结尾. 如果$出现在最后, 则表示这一行已经结尾了.
         * 下面的正则表达式表示, 以任意字符结尾
         */
        System.out.println("def".matches(".*$"));
        //以h开头
        System.out.println("hello sir".matches("^h.*"));
        //以ir结尾
        System.out.println("hello sir".matches(".*ir$"));
        /*
         * 下面这个语句的含义
         * ^h: 以h开头
         * \\w{0,3}: h后面跟着0-3个单词字符
         * o: 后面跟着一个o
         * \b: 表示的是单词的结尾. 
         * .*: 表示1个或多个字符
         * ir$: 以ir结尾
         */
        System.out.println("hello sir".matches("^h\\w{0,3}o\\b.*ir$"));
        /*
         * 下面这个案例返回false, 和上面的区别是, 单词hello, o不是单词的结尾
         */
        System.out.println("hellosir".matches("^h\\w{0,3}o\\b.*ir$"));
        
        /*
         * 如何匹配带有空格的空白行. 空白行虽然没有字符, 但是这一行可能有空白字符, 如空格等.
         * java中,换行用\n表示
         * 
         */
        System.out.println(" \n".matches("^[\\s&&[^\\n]]*\\n$"));
        

三、Pattern和Matcher

  1. mathes的用法:匹配整个字符串, 也就是判断是否整个字符串是否完全匹配正则表达式. 结果: false 分析:正则表达式是3-5个数组, 而str字符串第四个字符就不是数字, 所以返回false
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        //matches:匹配整个字符串--首先位数就不匹配, 所以返回false
        System.out.println(m.matches());
    }
  1. find()的用法:查找正则表达式,只要有符合条件的, 就返回true 结果: true true true false 分析: find是查找符合条件的字符串, 找到以后就把这个字符串吃了. 当在使用find查找的时候, 会在剩下的字符串中进行匹配, 所以, 前三个返回的是true,第四个返回的是false. fa
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        //find: 从整个字符串中查找, 返回的是,剩下的字符串
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
    }
  1. matches和find会相互影响 运行结果: false true true false false 分析: 这次为什么后两个find都是返回的false呢?因为第一个matches匹配到第四个字符的时候,正则表达式判断, 匹配失败. 那么下面再find查找的时候, 是从第五个字符开始的
代码语言:javascript
复制
package com.string;

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

public class RegexTest3 {

    public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        //matches:匹配整个字符串--首先位数就不匹配, 所以返回false
        System.out.println(m.matches());
        //find: 从整个字符串中查找, 返回的是,剩下的字符串
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
    }
}
  1. lookingAt:每次都是从头开始查找, 看是否有符合条件的. 运行结果: true true true true 分析: 每次都从头开始找, 所以,每次都能匹配成功
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        
        //lookingAt():从头开始查找
        System.out.println(m.lookingAt());
        System.out.println(m.lookingAt());
        System.out.println(m.lookingAt());
        System.out.println(m.lookingAt());
    }
  1. reset():重置。将光标移动到字符串的最开始。 我们在第3个例子中看到了。 matches方法的执行,影响到了find的运行。 加入我的find就要从字符串开始查找,怎么办呢, 使用reset() 运行结果: false true true true false 分析: 这样就可以看出, matches方法的运行,并没有影响到find。find查找到第四次的时候,查找失败了。
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        //matches:匹配整个字符串--首先位数就不匹配, 所以返回false
        System.out.println(m.matches());
        m.reset();
        //find: 从整个字符串中查找, 返回的是,剩下的字符串
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
        System.out.println(m.find());
}
  1. start()和end()方法:
    • 上面使用find()方法找到了字符串, 那么怎么知道找到的字符串的位置呢? 使用start()和end()就可查看位置了
    • start()和end()方法必须使用在能够find到字符的位置, 如果find返回false, 使用start和end会异常
    • start()和end():都是从0 开始计数. 返回的区间包括start,不包括end
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        //matches:匹配整个字符串--首先位数就不匹配, 所以返回false
        System.out.println(m.matches());
        m.reset();
        //find: 从整个字符串中查找, 返回的是,剩下的字符串
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
    }
代码语言:javascript
复制
public static void main(String[] args) {
        /**
         * 使用Matcher和Pattern匹配字符串
         */
        Pattern p = Pattern.compile("\\d{3,5}");
        String str = "123-45678-456-78";
        //将str和正则表达式p进行匹配
        Matcher m = p.matcher(str);
        
        //matches:匹配整个字符串--首先位数就不匹配, 所以返回false
        System.out.println(m.matches());
        m.reset();
        //find: 从整个字符串中查找, 返回的是,剩下的字符串
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
        System.out.println(m.start() + "-" + m.end());
        System.out.println(m.find());
    }
  1. replaceAll方法和appendReplacement()方法的使用
    • 案例一: 找到符合正则表达式的字符串,并打印输出. 很显然这里只能找到一个符合添加的. 那就是java. 其他大小写不符合.
    • 案例二: 不区分大小写, 替换所有的java为大写。 这里使用到了Pattern的另一个构造方法compile(regex, flag). flag有一些固定的值. 可以参考api
代码语言:javascript
复制
/**
         * replaceAll
         */
        Pattern pp = Pattern.compile("java");
        String ss = "java Java JaVa JAva IloveJava you hateJaVA ";
        Matcher mm = pp.matcher(ss);
        /*
         * 需求一: 找到所有符合条件字符串
         * 很显然, 只有一个符合条件, 找到并打印出来
         */
        if(mm.find()){
            //mm.group()打印输出这个组的内容
            System.out.println(mm.group());
        }

CASE_INSENSITIVE:大小写不敏感, 即不区分大小写. 我们这里使用的就是这个

代码语言:javascript
复制
/*
         * 需求二: 不区分大小写,查找所有符合条件的字符串, 将其替换为大写
         */
        //第二个参数代表,大小写不敏感
        Pattern pp2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
        String ss2 = "java Java JaVa JAva IloveJava you hateJaVA ";
        Matcher mm2 = pp2.matcher(ss);

        //查找替换直接使用replaceAll即可
        //下面这句话的含义: 查找所有符合条件的表达式,并将其替换为JAVA
        System.out.println(mm2.replaceAll("JAVA"));

      replaceAll: 查找并替换.

    • 案例三: 不区分大小写, 查找所有的字符串, 将奇数个替换为java, 偶数个替换为JAVA
代码语言:javascript
复制
//第二个参数代表,大小写不敏感
Pattern pp2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
String ss2 = "java Java JaVa JAva IloveJava you hateJaVA faddafdfa";
Matcher mm2 = pp2.matcher(ss);

/*
 * 需求三: 不区分大小写, 查找所有符合条件的字符串. 将其奇数个替换为java, 偶数个替换为JAVA
 * 
 * 方法有很多, 我们介绍一个Matcher的新方法appendReplacement()
 */
int num = 0;
StringBuffer buf = new StringBuffer();
while(mm2.find()){
    num ++;
    if(num % 2 == 0){
        mm2.appendReplacement(buf, "JAVA");
    } else {
        mm2.appendReplacement(buf, "java");
    }
}
//最后打印buffer, 因为最后的结果都填到buffer里面了
System.out.println(buf);
代码语言:javascript
复制
java JAVA java JAVA Ilovejava you hateJAVA
代码语言:javascript
复制
//第二个参数代表,大小写不敏感
Pattern pp2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
String ss2 = "java Java JaVa JAva IloveJava you hateJaVA fabdafdfa";
Matcher mm2 = pp2.matcher(ss);
/*
 * 需求三: 不区分大小写, 查找所有符合条件的字符串. 将其奇数个替换为java, 偶数个替换为JAVA
 * 
 * 方法有很多, 我们介绍一个Matcher的新方法appendReplacement()
 *  
 */
int num = 0;
StringBuffer buf = new StringBuffer();
while(mm2.find()){
    num ++;
    if(num % 2 == 0){
        mm2.appendReplacement(buf, "JAVA");
        System.out.println(buf);
    } else {
        mm2.appendReplacement(buf, "java");
        System.out.println(buf);
    }
}
//最后打印buffer, 因为最后的结果都填到buffer里面了
System.out.println(buf);
代码语言:javascript
复制
java
java JAVA
java JAVA java
java JAVA java JAVA
java JAVA java JAVA Ilovejava
java JAVA java JAVA Ilovejava you hateJAVA
java JAVA java JAVA Ilovejava you hateJAVA
代码语言:javascript
复制
//第二个参数代表,大小写不敏感
Pattern pp2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
String ss2 = "java Java JaVa JAva IloveJava you hateJaVA faddafdfa";
Matcher mm2 = pp2.matcher(ss);

//查找替换直接使用replaceAll即可
//下面这句话的含义: 查找所有符合条件的表达式,并将其替换为JAVA
System.out.println(mm2.replaceAll("JAVA"));
mm2.reset();
/*
 * 需求三: 不区分大小写, 查找所有符合条件的字符串. 将其奇数个替换为java, 偶数个替换为JAVA
 * 
 * 方法有很多, 我们介绍一个Matcher的新方法appendReplacement()
 *  
 */
int num = 0;
StringBuffer buf = new StringBuffer();
while(mm2.find()){
    num ++;
    if(num % 2 == 0){
        mm2.appendReplacement(buf, "JAVA");
        System.out.println(buf);
    } else {
        mm2.appendReplacement(buf, "java");
        System.out.println(buf);
    }
}
mm2.appendTail(buf);
//最后打印buffer, 因为最后的结果都填到buffer里面了
System.out.println(buf);
代码语言:javascript
复制
java JAVA java JAVA Ilovejava you hateJAVA faddafdfa
代码语言:javascript
复制
//第二个参数代表,大小写不敏感
Pattern pp2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
String ss2 = "java Java JaVa JAva IloveJava you hateJaVA faddafdfa";
Matcher mm2 = pp2.matcher(ss);

/*
 * 需求三: 不区分大小写, 查找所有符合条件的字符串. 将其奇数个替换为java, 偶数个替换为JAVA
 * 
 * 方法有很多, 我们介绍一个Matcher的新方法appendReplacement()
 */
int num = 0;
StringBuffer buf = new StringBuffer();
while(mm2.find()){
    num ++;
    if(num % 2 == 0){
        mm2.appendReplacement(buf, "JAVA");
    } else {
        mm2.appendReplacement(buf, "java");
    }
}
//最后打印buffer, 因为最后的结果都填到buffer里面了
System.out.println(buf);

  8. 分组group()分组. 下面来看案例

    • 案例一: 一个简单的小例子: 使用分组打印匹配成功的字符串 输出结果: 我们看到, 如预期的, 有三组满足条件. 那么, 如果我想要得到三组中每一组的数字,怎么办呢?看案例二
    代码语言:javascript
    复制
    45896aa
    758dd
    632ee
    • 案例二: 得到分组后,每一组的字符串. 这里有几个知识点
      • 使用()对正则表达式进行分组
      • 到底是第几组?从左括号开始计算, 第几个括号就是第几组
      • 分好的组可以通过group(组号) 获得相应的内容
      • 获取不存在的组将报异常
      • fda
      • fa 运行结果:
      代码语言:javascript
      复制
      获取整个组的内容
      45896aa
      758dd
      632ee
      获取第一组---全部是数字的组
      45896
      758
      632
      获取第二组---全部是字母的组
      aa
      dd
      ee
    代码语言:javascript
    复制
        /*
         * 案例二: 获得上一个案例中每一组的数字.
         * 
         * 这里才真正涉及到了分组的概念
         * 我们可以在正则表达式通过()来进行分组, 例如\\d{3,5}[a-z]{2}表示的时3-5个数字, 2个字符. 我们将数字分为一组, 字母分为一组. 
         * 正则表达式的写法如下(\\d{3,5})([a-z]{2}). 这样呢就分好组了, 其实, 在这里一共是有三组, 整个字符串也算作一组.
         * 
         * 分号组以后, 我们通过组号来获取每一组的内容. 如何知道我要获取的时哪一组呢? 看左括号, 第几个左括号,就是第几组.
         * 获取不存在的组将报异常
         */
        Pattern pp4 = Pattern.compile("(\\d{3,5})([a-z]{2})");
        String str4 = "45896aa-758dd-632ee-00a";
        Matcher mm4 = pp4.matcher(str4);
        System.out.println("获取整个组的内容");
        while(mm4.find()){
            System.out.println(mm4.group());
        }
        System.out.println("获取第一组---全部是数字的组");
        mm4.reset();
        while(mm4.find()){
            System.out.println(mm4.group(1));
        }
        System.out.println("获取第二组---全部是字母的组");
        mm4.reset();
        while(mm4.find()){
            System.out.println(mm4.group(2));
        }
代码语言:javascript
复制
    /**
     * 分组
     */
    /*
     * 案例一: 我们来看一个分组的简单例子
     */
    //这个正则表达式的含义是. 数字3-5个后跟两个字母
    Pattern pp3 = Pattern.compile("\\d{3,5}[a-z]{2}");
    String str3 = "45896aa-758dd-632ee-00a";
    Matcher mm3 = pp3.matcher(str3);
    
    /*
     * 分析: 这里面有几个符合条件呢?
     * 目测3个
     */
    while(mm3.find()){
        System.out.println(mm3.group());
    }

9. Qualifier: 限定符,修饰符

    在API文档中的限定修饰符有3类: 如下图

    仔细看这三类的描述会发现. 他们的注释都一模一样.

    第一类Greedy Quantifiers --> 贪婪的修饰符

    第二类 Reluctant quantifiers --> 不情愿的修饰符

    第三类 Possessive quantifiers --> 独占的修饰符

    而这三类中每一类对应的文字描述又都是一样的,那么, 他们到底有什么区别呢? 看下面的例子:

  • 第一类Greedy Quantifiers --> 贪婪的修饰符 运行结果: 0-10 结果分析: 运行结果: 0-10 Greedy Quanlifiers --贪婪的修饰符 工作原理 为什么叫她贪婪的呢? 因为, 他在匹配的时候首先匹配3-10个任意字符. 他会去自动匹配最多字符,10个. 这就是为什么说他是贪婪的原因 当匹配了10个字符以后, 发现不满足条件, 于是他减少一个, 看看是否满足条件, 如果满足,就直接反悔了
代码语言:javascript
复制
    String str = "aaaa9bbbb8";
    //贪婪的修饰符--Greedy Quanlifiers
    Pattern p1 = Pattern.compile("(.{3,10})[0-9]");
    Matcher m1 = p1.matcher(str);
    
    if(m1.find()){
        System.out.println(m1.start() + "-" + m1.end());
    }
    /**
     * 运行结果: 0-10
     * 
     * 结果分析: 
     * Greedy Quanlifiers --贪婪的修饰符  工作原理
     * 为什么叫她贪婪的呢? 因为, 他在匹配的时候首先匹配3-10个任意字符. 
     * 他会去自动匹配最多字符,10个. 这就是为什么说他是贪婪的原因
     * 当匹配了10个字符以后, 发现不满足条件, 于是他减少一个, 看看是否满足条件, 如果满足,就直接反悔了
     */
  • 第二类 Reluctant quantifiers --> 不情愿的修饰符 运行结果: 0-5 结果分析: * Greedy Quanlifiers --贪婪的修饰符 工作原理 * 为什么叫她贪婪的呢? 因为, 他在匹配的时候首先匹配3-10个任意字符. * 他会去自动匹配最多字符,10个. 这就是为什么说他是贪婪的原因 * 当匹配了10个字符以后, 发现不满足条件, 于是他减少一个, 看看是否满足条件, 如果满足,就直接反悔了
代码语言:javascript
复制
//不情愿的修饰符--Reluctant Quanlifiers
    String str = "aaaa9bbbb8";
    Pattern p2 = Pattern.compile("(.{3,10}?)[0-9]");
    Matcher m2 = p2.matcher(str);
    
    if(m2.find()){
        System.out.println(m2.start() + "-" + m2.end());
    }
    
    /**
     * 运行结果: 0-5
     * 
     * 结果分析: 
     * 不情愿的修饰符--Reluctant Quanlifiers  工作原理
     * 仅仅是多了一个问号, 为什么结果却变成了0-5个呢
     * 因为不情愿. 怎么个不情愿呢? 不是要匹配3-10个字符么, 那我就先匹配3个. 不情愿嘛. 
     * 匹配完3个,看看后面的字符是否符合条件.不符合, 那就在匹配四个, 四个符合了. 后面整个是一个数字.
     * 所以匹配的结果就是0-5了
     */
  • 第三类 Possessive quantifiers --> 独占的修饰符 运行结果: not match ! 结果分析 * 不情愿的修饰符--Reluctant Quanlifiers 工作原理 * 真奇怪, 怎么返回的是不匹配呢? * Reluctant Quanlifiers是这么工作的. 你不是要匹配3-10个字符么. 我就匹配10个, 然后看是否符合条件. * 如何条件则返回, 不符合条件的话我不会减少字符, 直接返回不匹配. * * 也就是按照最大字符进行匹配, 符合条件,匹配成功, 不符合条件, 对不起, 匹配失败.
代码语言:javascript
复制
    String str = "aaaa9bbbb8";
    //不情愿的修饰符--Reluctant Quanlifiers
    Pattern p3 = Pattern.compile("(.{3,10}+)[0-9]");
    Matcher m3 = p3.matcher(str);
    
    if(m3.find()){
        System.out.println(m3.start() + "-" + m3.end());
    }else{
        System.out.println("not match !");
    }
    /**
     * 运行结果: not match!
     * 
     * 不情愿的修饰符--Reluctant Quanlifiers 工作原理
     * 真奇怪, 怎么返回的是不匹配呢?
     * Reluctant Quanlifiers是这么工作的. 你不是要匹配3-10个字符么. 我就匹配10个, 然后看是否符合条件. 
     * 如何条件则返回, 不符合条件的话我不会减少字符, 直接返回不匹配.
     * 
     * 也就是按照最大字符进行匹配, 符合条件,匹配成功, 不符合条件, 对不起, 匹配失败.
     * 
     */

  9. 非捕获组-non capturing

    什么是非捕获组呢? 看看下面的案例

    • (?=x) API的解释 X, via zero-width positive lookahead. 这个解释不是很清楚, 我们来看案例 a) 下面这个案例是没有使用非捕获组. 匹配3个任意字符 输出结果 这个案例很简单. 为使用捕获组做个铺垫 2) 在上一个案例的基础上。有了新的要求, 要求第三个字符必须是数字2. 我们用常规思想如何实现呢?修改正则表达式
代码语言:javascript
复制
Pattern p11 = Pattern.compile(".{2}2");
String str11 = "ab2dd4";
Matcher m11 = p11.matcher(str11);
while(m11.find()){
    System.out.println(m11.group());
}
代码语言:javascript
复制
/**
 * non capturing--非捕获组
 * 什么是非捕获组呢? 我们来看看下面的案例
 */

/* 那么现在我提升需求: 要求打印出来的字符必须以数字2结尾.
 * 能够想到的做法是什么?
 * 正则表达式改为".{2}2", 这个肯定没问题
 * 我们还有一种方法,使用非捕获组  (?=X)
 * 
 * 我们知道?匹配的是0个或者1个字符. 当?在一个组中作为开头的时候, 表示的是非捕获组
 * 
 * 来看看下面你的demo
 */
Pattern p2 = Pattern.compile(".{3}(?=2)");
String str2 = "ab2dd4";
Matcher m2 = p2.matcher(str2);
while(m2.find()){
    System.out.println(m2.group());
}
代码语言:javascript
复制
Pattern p3 = Pattern.compile(".{3}(?=2)");
String str3 = "abc2dd4";
Matcher m3 = p3.matcher(str3);
while(m3.find()){
    System.out.println(m3.group());
}
代码语言:javascript
复制
Pattern p4 = Pattern.compile("(?=2).{3}");
String str4 = "abc2dd4";
Matcher m4 = p4.matcher(str4);
while(m4.find()){
    System.out.println(m4.group());
}
代码语言:javascript
复制
/**
 * .{3}(?!2)含义: 3个任意字符,后面跟着的不是2.
 */

Pattern p6 = Pattern.compile(".{3}(?!2)");
String str6 = "abc2dd4";
Matcher m6 = p6.matcher(str6);
while(m6.find()){
    System.out.println(m6.group());
}
代码语言:javascript
复制
/**
 * (?<=2)含义: 与(?=2)的含义正好相反. 
 * 
 * (?=2).{3} :任意3个字符, 以2开头
 * (?<=2).{3}:任意3个字符, 前面一个字符是2
 * 
 * .{3}(?=2): 任意三个字符, 后面紧跟着的一个字符是2
 * .{3}(?<=2): 任意三个字符, 三个字符中最后一个字符是2
 * 
 * 看下面的例子
 * 
 */
System.out.println("=====(?=2)在前======");
Pattern p7 = Pattern.compile("(?=2).{3}");
String str7 = "abc2dd4";
Matcher m7 = p7.matcher(str7);
while(m7.find()){
    System.out.println(m7.group());
}

System.out.println("=====(?<=2)在前======");
Pattern p8 = Pattern.compile("(?<=2).{3}");
String str8 = "abc2dd4";
Matcher m8 = p8.matcher(str8);
while(m8.find()){
    System.out.println(m8.group());
}


System.out.println("=====(?=2)在后======");
Pattern p9 = Pattern.compile(".{3}(?=2)");
String str9 = "abc2dd4";
Matcher m9 = p9.matcher(str9);
while(m9.find()){
    System.out.println(m9.group());
}


System.out.println("=====(?<=2)在后======");
Pattern p10 = Pattern.compile(".{3}(?<=2)");
String str10 = "abc2dd4";
Matcher m10 = p10.matcher(str10);
while(m10.find()){
    System.out.println(m10.group());
}
代码语言:javascript
复制
=====(?=2)在前======
2dd
=====(?<=2)在前======
dd4
=====(?=2)在后======
abc
=====(?<=2)在后======
bc2
代码语言:javascript
复制
  /**
 * 
 * (?<!2)的含义: 与(?!2)的含义正好想法
 * !2表示的是不是2
 * 
 * (?!2).{3} :任意三个字符,这三个字符中第一个字符不是2
 * .{3}(?!2): 任意三个字符, 这三个字符后面跟着的不是2
 * 
 * (?<!2).{3}:任意三个字符, 这三个字符的前一个字符不是2
 * 
 * .{3}(?<!2): 任意三个字符, 这三个字符中最后一个不是2
 * 
 * 看下面的例子
 * 
 */
System.out.println("=====(?!2)在前======");
Pattern p77 = Pattern.compile("(?!2).{3}");
String str77 = "abc2dd4";
Matcher m77 = p77.matcher(str77);
while(m77.find()){
    System.out.println(m77.group());
}

System.out.println("=====(?<!2)在前======");
Pattern p88 = Pattern.compile("(?<!2).{3}");
String str88 = "abc2dd4";
Matcher m88 = p88.matcher(str88);
while(m88.find()){
    System.out.println(m88.group());
}


System.out.println("=====(?!2)在后======");
Pattern p99 = Pattern.compile(".{3}(?!2)");
String str99 = "abc2dd4";
Matcher m99 = p99.matcher(str99);
while(m99.find()){
    System.out.println(m99.group());
}


System.out.println("=====(?<!2)在后======");
Pattern p100 = Pattern.compile(".{3}(?<!2)");
String str100 = "abc2dd4";
Matcher m100 = p100.matcher(str100);
while(m100.find()){
    System.out.println(m100.group());
}
代码语言:javascript
复制
=====(?!2)在前======
abc
dd4
=====(?<!2)在前======
abc
2dd
=====(?!2)在后======
bc2
dd4
=====(?<!2)在后======
abc
2dd
代码语言:javascript
复制
Pattern p1 = Pattern.compile(".{3}");
String str1 = "ab2dd4";
Matcher m1 = p1.matcher(str1);
while(m1.find()){
    System.out.println(m1.group());
}
    • 10. 向前引用 --back refenerence, 看例子, 了解其含义 运行结果: 如果字符串变成1234,那么返回的结果就是ifalse了
代码语言:javascript
复制
System.out.println("=====back Refenences:======");
Pattern p110 = Pattern.compile("(\\d\\d)\\1");
String str110 = "1234";
Matcher m110 = p110.matcher(str110);
System.out.println(m110.matches());
代码语言:javascript
复制
=====back Refenences:======
false
代码语言:javascript
复制
/**
 * back Refenences:向前引用
 * "(\\d(\\d))\\2" : 正则表达式的含义, 有两个组, 后面的内容和第二组的内容保持一致
 */
System.out.println("=====back Refenences:======");
Pattern p110 = Pattern.compile("(\\d(\\d))\\2");
String str110 = "122";
Matcher m110 = p110.matcher(str110);
System.out.println(m110.matches());
代码语言:javascript
复制
/**
 * back Refenences:向前引用
 * \\1 表示的是第一组, 表示和第一组的内容保持一致
 */
System.out.println("=====back Refenences:======");
Pattern p110 = Pattern.compile("(\\d\\d)\\1");
String str110 = "1212";
Matcher m110 = p110.matcher(str110);
System.out.println(m110.matches());

/**
 * "(\\d\\d)\\1" : (\\d\\d)表示的是一个组, 这个组里有两个数字. \\1,表示的是, 后面跟着的数组和第一组一致
 * 来看字符串1212: 两个数字匹配到12. 后面的字符串要和第一个组一致. 所以也是12. 匹配成功
 */
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档