• 正则表达式的学习心得


    一、正则表达式说明

    ​ 正则表达式是针对字符串的提取,所有语言都支持,不管是前端的JS还是后端PHP,还包含了测试工具Jmeter,SQL,Linux上的find等等,对于开发来说,很重要,并且掌握后对一些字符工具操作会很方便

    ​ 正则表达式主要是使用各类符号或者字母来表达,用到的符号看似很多,但有些符号是从另外的符号中扩展而来的,比如想要匹配一个数字时可以使用 [0-9] ,也可以用\d来简化写法,\d就是扩展用来匹配数字的。扩展的符号多了看上去匹配词就感觉很多,实则先学习它基本的匹配词后再去记扩展词就会容易很多。

    ​ 学习正则的时候可以将使用到的符号就行分为几大类,先从基础的匹配到复杂的提取,层级递进从而达到螺旋式上升。比如[0-9]代表匹配0到9数字;{2}代表至少满足两次前面的字符,连起来就是[0-9]{2}就是一个正则表达式,能匹配到的长度为2的数字;^ 代表开头,连起来就是^[0-9]{2},匹配以两位数字开头字符。

    二、正则语法

    首先我将正则使用到的符号分为几大类:匹配符、限定符、定位符、装饰符和运算符号的优先级来就行练习,逐一掌握

    2.1、字符匹配

    在一串字符中,想要匹配数字、字母或者是符号,我们就可以根据这些特性然后使用特定的字符来做匹配提取

    字符说明
    .匹配所有单个字符,除了\r\n
    |或者,当表达式中出现非关键字的字符时就代表需匹配该字符。使用`
    []包含其中的一个字符,例如[abc]匹配"are"里的a
    -字符范围。匹配指定范围内的任何字符。例如,[a-z]匹配"a"到"z"范围内的任何小写字母。
    [^]^与[]搭配是反向匹配。匹配未包含的字符,例如[^abc] 匹配非abc的字符,还能反向范围[^a-b]
    \n换行符匹配
    \f换页符匹配
    \r匹配一个回车符
    \v垂直制表符匹配
    \转义符,标记下一个字符标记为特殊字符

    如上是基础的字符匹配,为了简化表达式,又就行了一些常用的匹配做了扩展,于是有了

    字符说明
    \d匹配数字,等效于[0-9]
    \D匹配非数字,等效与[^0-9]
    \w匹配任何字类字符,包括下划线。等效[A-Za-z0-9_]
    \W与任何非单词字符匹配。与[^A-Za-z0-9_]等效。可以用来找符号。
    \s匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
    \S匹配任何非空白字符。与 [^\f\n\r\t\v] 等效。

    2.2、限定符

    一个匹配符一次只能匹配一个符号,那么要匹配多少个也需要指定,也就是限定符。

    字符说明
    {n}n是正整数,代表着正好匹配n次,例如a{3} 匹配到的是aaa, aa匹配不到
    {n,}n是正整数,代表匹配n或者n次以上,
    {n,m}n和m是正整数且n <= m,代表着匹配至少n次,最多m次
    *零次或多次匹配。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。
    +一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。
    ?零次或一次匹配前面的字符或子表达式。例如,"do(es)?“匹配"do"或"does"中的"do”。? 等效于 {0,1}。
    ??或者+?当此字符(?)在任意限定符的后面时,它的作用不再是限定符了,而是将匹配模式换成”非贪心“,这种模式是将匹配到的字符尽可能的短。例如o+ 在oooooo匹配到的是全部,使用o{2,}?则会只匹配到前两个o

    2.3、定位符

    在一串字符中,可以规定从哪里开始匹配,比如开头,或者结尾

    字符说明
    ^匹配字符的开始位置
    $匹配字符的结束位置
    \b匹配一个字边界,代表单词的开头或者结尾,单词之间由标点符号或者空格来分隔,但\b不会认为用逗号分割的为边界。需要配合匹配符来使用例如:\ba 匹配开头的a; [1-9]\b 以数字结尾的
    \B匹配非边界字符。

    2.4、优先符顺序说明

    正则表达式从左开始运算,并遵循优先级顺序,和算数表达式类似。优先级如下,高到低

    字符描述
    \转义符
    (),[],(?😃圆括号和方括号
    *,+,?,{}限定符
    ^,$,\普通字符,普通字符定位符和匹配符
    |或者

    2.5、装饰符

    正则表达式的标记用于指定额外的匹配策略。

    //Java写法如下,其他的不知道
    Pattern pattern = Pattern.compile("(?i)Java");
    
    • 1
    • 2
    字符描述
    iignore的缩写,代表不区分大小写
    gglobal的缩写,代表全局匹配
    mmulti line 多行匹配
    s. 匹配所有单个字符除\r\n,使用s则可以匹配\n

    三、在Java中使用正则

    java.util.regex是一个用正则表达式对字符串就行匹配工作的类库包,它包括了两个类:Pattern和Matcher。

    1、Pattern

    Pattern类用于创建一个正则表达式,也可以说是创建一个匹配模式

    1.1、compile(String regex)

    静态方法创建Pattern对象,regex为正则表达式

    Pattern pattern = Pattern.compile("Java");
    // 返回此模式的正则表达式即Java
    System.out.println(pattern.pattern());
    
    • 1
    • 2
    • 3
    1.2、compile(String regex,int flags)

    静态方法创建Pattern对象,regex为正则表达式,flags为可选模式,如:Pattern.CASE_INSENSITIVE 忽略大小写;Pattern.DOTALL此模式下 .会匹配换行符,默认匹配模式下 .不会匹配换行符。等等,具体可参照Pattern的多种匹配模式。

    Pattern pattern = Pattern.compile("Java", Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher("java");
    //返回true,如果使用默认匹配规则则为false
    System.out.println(matcher.matches());
    
    • 1
    • 2
    • 3
    • 4
    参数说明
    Pattern.CASE_INSENSITIVE忽略大小写
    Pattern.DOTALL. 匹配所有单个字符除\r\n,使用s则可以匹配\n
    Pattern.MULTILINE开启多行匹配,^ $在默认的情况下只会匹配第一行,设置了MULTILINE模式回匹配所有行。
    1.3、matches(String regex, CharSequence input)

    静态方法,判断input 是否匹配给定的正则表达式,注意的是该方法适合用于只匹配一次,且匹配全部字符串

    //返回true
    Pattern.matches("\\d+","2223");
    //返回false,需要匹配到所有字符串才能返回true,这里aa不能匹配到
    Pattern.matches("\\d+","2223aa");
    
    • 1
    • 2
    • 3
    • 4
    1.4、split(CharSequence input)

    用于分隔字符串,并返回一个String[]

    Pattern compile = Pattern.compile("\\d+");
    //abc,def,g
    String[] strArray = compile.split("abc1231def3g");
    
    • 1
    • 2
    • 3

    2、Matcher

    匹配器,对正则表达式的分组支持,以及对正则表达式的多次匹配支持,需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

    2.1、matches()

    整个字符进行匹配,只有整个字符序列完全匹配成功才返回true。

    Pattern compile = Pattern.compile("\\d*");
    Matcher matcher = compile.matcher("123a");
    boolean status = matcher.matches();
    
    • 1
    • 2
    • 3
    2.2、索引方法start()和end()

    在调用匹配方法时,会移动指针到匹配词所在字符的索引,默认是在0位置上,start为初始索引,end为所在的索引之后的一个偏移量。

    Pattern pattern = Pattern.compile("\\d+");
    Matcher matcher = pattern.matcher("123dfdf3424r");
    boolean status = matcher.find();
    if (status){
        // 0
    	System.out.println(matcher.start());
        // 3
    	System.out.println(matcher.end());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    2.3、lookingAt

    部分匹配,从第一个字符进行匹配,符合返回true并且不再继续匹配,失败了也不再继续匹配直接返回false。

    Pattern compile1 = Pattern.compile("\\d");
    //返回true
    Matcher matcher1 = compile1.matcher("123");
    //返回false
    Matcher matcher2 = compile1.matcher("d123");
    
    //返回false
    Pattern compile2 = Pattern.compile("\\d{1,3}");
    Matcher matcher = compile.matcher("ddds123");
    
    
    //返回false
    Pattern compile = Pattern.compile("\\d{1,3}");
    Matcher matcher = compile.matcher("ddds123");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    2.4、find()和find(int start)

    部分匹配,从当前位置开始匹配,找到一个匹配的子串,将移动下次匹配的位置。也可以使用find(int start)方法,从指定位置开始匹配

    2.5、reset()

    前面调用匹配方法,指针会移动,使用reset()将指针重置为0

    2.6、groupCount()

    返回该正则表达式中的子序列,就是以()圈起来的表达式数量,不是计算匹配数

    Pattern compile = Pattern.compile("(\\d[abc])a(\\d([a]3))");
    Matcher matcher = compile.matcher("123abc45b6");
    //这里可以简化成()(()),总共有三对口括号,所以为3
    System.out.println("找到-->"+matcher.groupCount());
    
    • 1
    • 2
    • 3
    • 4
    2.7、grop()和grop(int grop)

    当匹配到一串字符的时候,它可能是由多个子序列匹配构成的,使用grop()是获取到完整匹配字符,grop(0)等同与grop(),grop(int grop)是获取指定子序列匹配的字符

    String line = "123ra9040";
    String pattern = "(\\d+)([a-z]+)(\\d+)";
    
    Pattern r = Pattern.compile(pattern);
    Matcher m = r.matcher(line);
    
    while (m.find( )) {
        //获取完整的匹配字符->123ra9040
        System.out.println("Found value: " + m.group(0) );
        //获取(\\d+)匹配到->123
        System.out.println("Found value: " + m.group(1) );
        //获取([a-z]+)匹配到->ra
        System.out.println("Found value: " + m.group(2) );
        //获取
        System.out.println("Found value: " + m.group(3) );
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    括号嵌套先找范围小的括号,如下:

    
    Pattern compile = Pattern.compile("((\\d[abc])b)");
    Matcher matcher = compile.matcher("123abc45b6");
    
    while (matcher.find()){
        //3ab
    	System.out.println(matcher.group());
        //((\\d[abc])b) 3ab
    	System.out.println(matcher.group(1));
        // (\\d[abc])  3a
    	System.out.println(matcher.group(2));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    grop(int grop) 中,grop范围可以使用groupCount()方法来确定子序列个数

    四、常见的怎则表达式

    #纯数字
    ^[0-9]*$
    
    
    #n位数字
    ^\d{n}$
    
    #只能输入汉字
    ^[\u4e00-\u9fa5]{0,}$ 
    
    #邮箱
    \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
    
    # 匹配网址URL的正则表达式
    [a-zA-z]+://[^\s]*
    
    # 手机号
    /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    参考文献

    https://blog.csdn.net/weixin_43501172/article/details/115655288
    
    ## 匹配模式
    https://blog.csdn.net/BaymaxCS/article/details/119281231
    
    https://www.cnblogs.com/54chensongxia/archive/2020/12/16/14145325.html
    
    https://www.runoob.com/regexp/regexp-syntax.html
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    c4d和blender哪个简单?哪个好用?
    VMware的三种连接模式
    C++11 - 1 - Initializer_list
    如何在小程序里实现一个随机关注列表?
    顾问们眼中的顾问
    3A4000架构银河麒麟V10编译安装filezilla
    2023年中国新能源汽车电动助力转向系统行业现状分析:随着新能源汽车的发展,产品渗透率的提升[图]
    Bug: conda环境与jupyter notebook kernel核环境不一致
    猿创征文 |【C++】面向对象之微观部分——类的组成(中)
    Tracing Analysis Solution
  • 原文地址:https://blog.csdn.net/qq_39381892/article/details/126272000