h

hellotqq

V1

2023/02/03阅读:19主题:默认主题

一文搞定正则表达式

本篇文章来学习下正则表达式,文章主要通过代码和代码中的注解进行展开,本文的结构如下:

  • 1、认识正则表达式
  • 2、匹配规则
  • 3、复杂匹配规则
  • 4、分组分配
  • 5、非贪婪匹配
  • 6、分割、查找、替换、反向引用

1、认识正则表达式

  • 正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。下面通过一个简单的例子来认识下正则表达式。
public class MatchesDemo1 {
    /**
     * 正则表达式简介
     * @param args
     */

    public static void main(String[] args) {
        /**
         * 判断用户输入的年份为20##年,规则如下:
         * 一共4个字符,分别是2,0,0-9任意数字,0-9任意数字
         * 对应的正则表达式就是:20\d\d,其中\d表示任意一个数字
         * 把正则表达式转化为java字符串就变成了“20\\d\\d”,java字符串用“\\”表示“\”
         */

        String regex = "20\\d\\d";
        System.out.println("2017".matches(regex)); //true
        System.out.println("2100".matches(regex)); //false
    }
}

2、匹配规则

public class 匹配规则 {
    /**
     * 正则表达式的匹配规则是从左到右匹配,
     * 如果正则表达式中有特殊字符,要用“\”来转义,如“\&”用来匹配特殊字符“&”
     *      要注意的是,正则表达式在Java中也是一个字符串,因此,对于正则表达式“a\&c”对应的Java字符串应该是“a\\&c”,
     * 因为“\”也是Java字符的转义字符,两个“\\”实际上表示的是“\”
     *      如果想要匹配非ASCII字符,例如中文,用Unicode编码如:你好 \u4f60\u597d
     * @param args
     */

    public static void main(String[] args) {
        test7();
    }
    static void test1(){
        String re1 = "abc";
        System.out.println("abc".matches(re1));//true
        System.out.println("Abc".matches(re1));//false
        System.out.println("ABC".matches(re1));//false

        String re2 = "a\\&c";
        System.out.println("a&c".matches(re2));//true
        System.out.println("a-c".matches(re2));//false
        System.out.println("a&&c".matches(re2));//false
        System.out.println("你好".matches("\u4f60\u597d"));//true
    }

    /**
     * 匹配任意字符
     * 用“.”匹配一个任意字符
     */

    static void test2(){
        System.out.println("a*9".matches("a.9"));//true

    }
    /**
     * 匹配数字
     * \d可以匹配0-9的任意数字
     */

    static void test3(){
        System.out.println("ab9".matches("ab\\d"));//true
    }

    /**
     * 匹配常用字符
     * \w可以匹配一个字母、数字、下划线,w的意思是word
     */

    static void test4(){
        System.out.println("a3".matches("\\w3"));//true
        System.out.println("A3".matches("\\w3"));//true
        System.out.println("03".matches("\\w3"));//true
        System.out.println("_3".matches("\\w3"));//true
    }
    /**
     * 匹配空格字符
     * \s匹配空格包括空格和tab字符(在Java中用\t表示)
     */

    static void test5(){
        System.out.println("a\tb".matches("a\\sb"));//true
        System.out.println("a b".matches("a\\sb"));//true
    }

    /**
     * 匹配非数字
     * \d匹配数字,\D匹配非数字
     * 类似的,\W可以匹配\w不能匹配的字符,\S可以匹配\s不能匹配的字符
     */

    static void test6(){
        System.out.println("a0".matches("a\\D")); //false
        System.out.println("ab".matches("a\\D"));//true
        System.out.println("aB".matches("a\\D"));//true
        System.out.println("a_".matches("a\\D"));//true
        System.out.println("a*".matches("a\\D"));//true
    }

    /**
     * 重复匹配
     * 修饰符”*“可以匹配任意个字符,包括0个、1个、多个,相当于{0,}
     * 修饰符”+“可以匹配至少一个字符 包括1个、多个
     * 修饰符”?“可以修饰0个或者1个字符
     * {n}精确指定几个字符
     * {n,m}指定匹配n~m个字符
     * {n,}为至少匹配n个字符
     */

    static void test7(){
        System.out.println("A234".matches("A\\d{2,}"));//true
    }
}

3、复杂匹配规则

public class 复杂匹配规则 {
    public static void main(String[] args) {
        test4();
    }

    /**
     * 匹配开头和结尾
     * 正则表达式多行匹配时,我们用"^"表示开头,”$“表示结尾
     */

    static void test1(){
        String str  = "A\\d{3}$";
        System.out.println("A009".matches(str));//true
        System.out.println("A123".matches(str));//true
    }

    /**
     * 匹配指定范围
     *
     * 使用[……]可以匹配范围内的字符,如[123456789]可以匹配1~9,但是把所有的字符全列出来有点麻烦,
     * [……] 还有一种写法,[1-9]
     * 要匹配大小写不限的十六进制数,如1A2b3c,我们可以这样写[0-9a-fA-F]
     * 匹配6位的16进制数可以写[0-9a-fA-F]{6}
     *
     * [...]还有一种排除法,即不包含指定范围的字符,假设我们要匹配任意字符,但不包含数字,可以写[^0-9]{3}
     */

    static void test2(){

    }

    /**
     * 或规则匹配
     *
     * 用"|"连接的两个正则规则是或规则,如ab|cd可以匹配ab或cd
     */

    static void test3() {
        String re = "html|css|js";
        System.out.println("html".matches(re)); //true
        System.out.println("css".matches(re));//true
        System.out.println("js".matches(re));//true

    }

    /**
     * 使用括号
     * 现在要进行匹配learn html、learn css 、learn js ,要是用learn\shtml|learn\scss|learn\sjs就太麻烦了,我们可以把公共部分提出来
     * 然后用(。。。)把子规则括起来表示成learn\s(java|php|go)
     */

    static void test4(){
        String re = "learn\\s(html|css|js)";
        System.out.println("learn html".matches(re));//true
        System.out.println("learn css".matches(re));//true
        System.out.println("learn js".matches(re));//true
    }

}

4、分组分配

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

public class 分组分配 {
    public static void main(String[] args) {
        test1();
    }

    /**
     * 问题:010-4657858这样的电话号码,如何判断后还方便将区号和号码分别提取出来呢?
     *引入java.util.regex包,用Pattern对象匹配,匹配后获得一个Matcher对象,如果匹配成功,就可以直接从Matcher.group(index)返回字串。
     *
     * Matcher.group(index)方法的参数用1表示第一个子串,2表示第二个子串。如果我们传入0会得到什么呢?答案是010-12345678,即整个正则匹配到的字符串。
     *
     * 使用Matcher时,必须首先用mather判断,为true时,才可以调用group获取字串
     * String。matches()方法内部调用的就是Pattern和Matcher类的方法
     */

    static void test1(){
        Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
        Matcher m = p.matcher("010-1234567");
        if (m.matches()) {
            String group1 = m.group(1);
            String group2 = m.group(2);
            String group0 = m.group(0);
            System.out.println(group1); //010
            System.out.println(group2);  //1234567
            System.out.println(group0);  //010-1234567
        }else {
            System.out.println("匹配失败!");
        }

    }
}

5、非贪婪匹配

  匹配次数中的贪婪模式(匹配字符越多越好,默认)
  匹配次数中的非贪婪模式(匹配字符越少越好,修饰匹配次数的特殊符号后再加上一个“?”号)
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 本接任务:区分?的含义,\d??
 */

public class 非贪婪匹配 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
    }

    /**
     * 下面的这个例子:
     * 我们是期望获得123 和00000这两个的,结果group1结构就是12300000而group2是空字符串,
     * 得到这个结果也可以理解吧,因为\d+把后面的0也包括进来了
     * 为了让\d+尽可能的少匹配,0*尽可能多的多匹配,我们使用非贪婪匹配,在\d后加上?
     */

    static void test1(){
        Pattern pattern = Pattern.compile("(\\d+)(0*)");
        Matcher matcher = pattern.matcher("12300000");
        if (matcher.matches()) {
            System.out.println("group1="+matcher.group(1)); //group1=12300000
            System.out.println("group2="+matcher.group(2)); //group2=
        }
    }
    static void test2(){
        Pattern pattern = Pattern.compile("(\\d+?)(0*)");
        Matcher matcher = pattern.matcher("12300000");
        if (matcher.matches()) {
            System.out.println("group1="+matcher.group(1)); //group1=123
            System.out.println("group2="+matcher.group(2)); //group2=00000
        }
    }
    static void test3(){
        Pattern pattern = Pattern.compile("(\\d??)(9*)");
        Matcher matcher = pattern.matcher("1999999999");
        if (matcher.matches()) {
            System.out.println("group1="+matcher.group(1)); //group1=1
            System.out.println("group2="+matcher.group(2)); //group2=999999999
        }
    }
}

6、分割、查找、替换、反向引用

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

public class SearchAndReplace {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
        test4();
    }
    /**
     * 分割字符串
     * 使用正则表达式分割字符串可以实现更加灵活的功能,String.split()方法传入的是正则表达式,
     * 如果我们想让用户传入一组标签,然后将标签提取出来,因为用户的输入往往是不规范的,如果我们使用合适的
     * 正则表达式就可以消除多个空格、混合“,”“;”等不规范的输入,直接提取出规范的字符串
     */

    static void test1(){
        String[] split = "a b c".split("\\s"); //[a, b, c]
        System.out.println(Arrays.asList(split));
        String[] split1 = "a b    c".split("\\s"); //[a, b, , , , c]
        System.out.println(Arrays.asList(split1));
        String[] split2 = "a,b  ;; , c".split("[\\,\\;\\s]+");//[a, b, c]
        System.out.println(Arrays.asList(split2));
    }

    /**
     * 搜索字符串
     */

    static void test2(){
        String s = "the quick brown fox jumps over the lazy dog.";
        Pattern p = Pattern.compile("\\wo\\w");
        Matcher m = p.matcher(s);
        while (m.find()) {
            String substring = s.substring(m.start(), m.end());
            System.out.println(substring);
        }
        //row
        //fox
        //dog
    }
    /**
     * 替换字符串
     *
     * 正则表达式替换字符串可以直接调用String。replaceAll(),它的第一个参数是正则表达式,第二个参数式待替换的字符串
     */

    static  void test3(){
        String s = "The     quick\t\t brown   fox  jumps   over the  lazy dog.";
        String r = s.replaceAll("\\s+"" ");
        System.out.println(r); // "The quick brown fox jumps over the lazy dog."
    }

    /**
     * 反向引用
     * 如果我们要把搜索到的指定字符串按规则替换,比如前后各加一个<b>xxxx</b>,这个时候,使用replaceAll()的时候,我们传入的第二个参数可以使用$1、$2来反向引用匹配到的子串
     */

    static void test4(){
        String s = "the quick brown fox jumps over the lazy dog.";
        String r = s.replaceAll("\\s([a-z]{4})\\s"" <b>$1</b> ");
        System.out.println(r); //the quick brown fox jumps <b>over</b> the <b>lazy</b> dog.
    }
}

欢迎转载,转载请注明原文出处@hellotqq 个人公众号 :hellotqq, gitee:hellotqq(常用) github:hellotqq(不常用) CSDN:hellotqq 稀土掘金:hellotqq 博客园:hellotqq 欢迎关注交流与您共同成长!

分类:

后端

标签:

Java

作者介绍

h
hellotqq
V1