定制开发小程序39、一篇文章弄懂 Java 正则表达式中的量词、贪婪、勉强、独占和 String 的 matches 方法的底层【个人感觉非常值得学习】

文章目录

一、量词(Quantifier)

📝 量词定制开发小程序用以标记某个字符出现的次数

贪婪(Greedy)勉强(Reluctant)独占(Possessive)含义
🍀{n}🍀{n}?🍀{n}+🍀 出现 n 次
🍀{n,m}🍀{n,m}?🍀{n,m}+🍀出现 n 到 m 次
🍀{n,}🍀{,}?🍀{n,}+🍀出现至少 n 次
🍀?🍀??🍀?+🍀出现 0 次或者 1 次
🍀*🍀*?🍀*+🍀定制开发小程序出现任意次
🍀+🍀+?🍀++🍀定制开发小程序至少出现一次

📝 贪婪、勉强、定制开发小程序独占的区别很大,定制开发小程序后面介绍比较合适

二、字符串的 matches 方法底层

📜 String 的 matches 定制开发小程序方法底层用到了 PatternMatcher





public class TestDemo {    public static void main(String[] args) {        String input1 = "111庆222";        String input2 = "111庆";        String r = "1{3}庆";        // Pattern 的 matchers 匹配的是【整个】字符串        // match the entire region against the pattern.                // input1.matches(r): 看一看 input1 定制开发小程序字符串是否完全匹配正则表达式 r        System.out.println(input1.matches(r)); // false                System.out.println(input2.matches(r)); // true    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

三、 类的其他方法

📜 上一节中了解了 Matcher 类的 matches 方法【如果整个 input(字符串)和,则返回 true】,这也是 String 的 matches 方法的底层

通过下面的代码引出 Matcher 类的其他方法:

public class TestDemo {    public static void main(String[] args) {        String input0 = "520";        String input1 = "888";        String input2 = "111_222_666";        String r = "\\d{3}";        System.out.println(input0.matches(r)); // true        System.out.println(input1.matches(r)); // true        // (1) 字符串的 matches 方法底层的 Matcher 类的 matches 方法是匹配整个字符串        // (2) 必须整个字符串和正则模式匹配(必须整个字符串和正则模式匹配)        // (3) input2 里面包含三个数字, 但不仅仅只是有三个数字, 无法和正则完全匹配        System.out.println(input2.matches(r)); // false    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

📜 上面代码中的 input2 无法完全匹配正则表达式 r(这是字符串底层 Matcher 类的 matches 方法的结果)
📜 matches 方法是对整个字符串进行匹配,必须整个字符串匹配正则表达式
📜 Matcher 类的 find 方法可以把字符串的部分序列和正则进行匹配,如果匹配成功,返回 true


(1) find、start、end、group

public class TestDemo {    public static void main(String[] args) {        String input = "111_222_666";        String r = "\\d{3}";        System.out.println(input.matches(r)); // false        // 假如正则表达式 r 语法错误, 会抛异常        Pattern pattern = Pattern.compile(r);        Matcher matcher = pattern.matcher(input);        // 如果调用 matches 方法, 则和 String 的 matches 方法返回的结果一样        System.out.println(matcher.matches()); // false        // input 中有子序列满足正则表达式 r 则返回 true        System.out.println(matcher.find()); // true    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

📝 find: 如果从 input(给定字符串)中能够找到与 regex 匹配的子序列,则返回 true
📝 如果能够匹配成功,可以通过 startendgroup 方法获取更多的信息
📝 每次的查找范围会先剔除之前已经查找过的范围

📝 start: 返回上一次匹配成功的开始索引

📝 end: 返回上一次匹配成功的结束索引

📝 group: 返回上一次匹配成功的子序列

public class TestDemo {    public static void main(String[] args) {        String input = "111_222_666";        String r = "\\d{3}";        Pattern pattern = Pattern.compile(r);        Matcher matcher = pattern.matcher(input);        boolean findResult = matcher.find();        System.out.println(findResult); // true        if (findResult) {            System.out.println("匹配的子序列: " + matcher.group());            System.out.println("起始索引: " + matcher.start());            System.out.println("结束索引: " + matcher.end());        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(2) find 细节


📝 该方法(find)会从给定 input 的一开始(第一个字符)开始匹配
📝 但若该方法先前的调用是成功的,并且 matcher 还没有被重置,则从先前的匹配中还没有被匹配过的字符开始匹配

📜 matcher 还没有被重置: matcher 是通过 input(给定字符串)创建的
📜 只要 input 没有改变, matcher 就没有被重置

📝 find 方法被调用一次,就会在该 input 中匹配一次(从前往后匹配)


取出所有符合正则表达式的子序列:

public class TestDemo {    public static void main(String[] args) {        String input = "520_222_666";        String r = "\\d{3}";        Pattern pattern = Pattern.compile(r);        Matcher matcher = pattern.matcher(input);        // 当无法匹配到满足正则的子序列时, 结束循环        while (matcher.find()) {            System.out.println(matcher.group());        }                /*            520            222            666         */    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

(3) 封装:中匹配正则的子串

    /**     * 返回给定字符串中所有成功匹配正则表达式的子串     *     * @param input 给定字符串     * @param regex 正则表达式     * @return 成功匹配正则表达式的子串 List     */    public static List<String> okMatchRegexSubstrList(String input, String regex, int flags) {        if (input == null || regex == null) return null;        List<String> subStrings = new ArrayList<>();        Pattern p = Pattern.compile(regex, flags);        Matcher m = p.matcher(input);        while (m.find()) {            subStrings.add(m.group());        }        return subStrings;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、贪婪、勉强、独占

🎄 贪婪:
✏️ ① 先 “吞掉” 整个 input 进行匹配
✏️ ② 若匹配失败,则吐出最后一个字符,然后再次尝试匹配
✏️ ③ 重复该操作

public class TestDemo {    public static void main(String[] args) {        String regex = ".*good";        String input = "庆の6good8浩のgoodMorning";        List<String> ret = okMatchRegexSubstrList(input, regex, 0);        // 贪婪: [庆の6good8浩のgood]        printList("贪婪", ret, ", ");    }    /**     * 打印字符串 List     */    public static void printList(String desc, List<String> list, String divider) {        int size = list.size();        if (size == 0) {            System.out.println("空数组");            return;        }        System.out.print(desc + ": [");        for (int i = 0; i < list.size(); i++) {            if (i != list.size() - 1) {                System.out.print(list.get(i) + divider);            }            System.out.print(list.get(i));        }        System.out.print("]");    }    public static List<String> okMatchRegexSubstrList(String input, String regex, int flags) {        if (input == null || regex == null) return null;        List<String> subStrings = new ArrayList<>();        Pattern p = Pattern.compile(regex, flags);        Matcher m = p.matcher(input);        while (m.find()) {            subStrings.add(m.group());        }        m.reset();        return subStrings;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

🎄 勉强:
✏️ ① 先 “吞掉” input 的第一个字符进行匹配
✏️ ② 若匹配失败,则再吞掉下一个字符,然后再次尝试匹配
✏️ ③ 重复该操作

public class TestDemo {    public static void main(String[] args) {        String regex = ".*?good";        String input = "庆の6good8浩のgoodMorning";        List<String> ret = okMatchRegexSubstrList(input, regex, 0);        // 勉强: [庆の6good, 庆の6good8浩のgood]        printList("勉强", ret, ", ");    } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

🎄 独占:
✏️ “吞掉” 整个 input 进行唯一的一次匹配(类似 equals 方法)

public class TestDemo {    public static void main(String[] args) {        String regex = ".*+good";        String input = "庆の6good8浩のgoodMorning";        List<String> ret = okMatchRegexSubstrList(input, regex, 0);         // 空数组        printList("独占", ret, ", ");    } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结束,如有错误!请赐教

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发