正则表达式学习笔记

1.1 正则表达式

1.1.1好处

  • 一个正则表达式就是一个描述规则的字符串
  • 只需要编写正确的规则,就可以让正则表达式引擎去判断目标字符串是否符合规则
  • 正则表达式是一套标准,可以用于任何语言
  • JDK 内置正则表达式引擎: java.util.regex
    示例:判断用户输入的年份是否是19xx年:
java 复制代码
public class TestRegex {
    // \\为转义字符,d 代表0-9的数字
    public static boolean is19xx(String s) {
        if(s == null) {
            return false;
        }
        return s.matches("19\\d\\d");
    }

    public static void main(String[] args) {

        System.out.println(is19xx("1991")); // true
        System.out.println(is19xx("1900")); // true
        System.out.println(is19xx("1911")); // true
        System.out.println(is19xx("1934")); // true

        System.out.println(is19xx(" ")); // false
        System.out.println(is19xx(null)); // false
        System.out.println(is19xx("19910")); // false
        System.out.println(is19xx("A90")); // false
        System.out.println(is19xx("2022")); // false
    }
}

1.1.2 匹配规则

  • 从左到右按规则匹配

1.1.3 如何编写正则表达式:

  • 精确匹配"abc"

    -

  • 精确匹配: "a\&c",特殊字符需要转义:

  • 精确匹配: "a\548cc",非ascII 字符 用\u#### 表示

  • 特殊字符 . 可以匹配一个任意字符: "a.c"

  • 符号\d可以匹配一个数字: "00/d"

  • 符号 \w 可以匹配一个字母,数字或者下划线: "java\w"

  • 符号 \s 可以匹配一个空白字符 "A\sB"

  • 符号\D 可以匹配一个非数字 : "00\D":

  • 符号\W 可以匹配一个非字母,数字或下划线: "java\W"

  • 符号 \S 可以匹配一个非空白字符:"A\SB"

  • 修饰符 * 可以匹配任意个字符:"A\d*"

  • 修饰符 + 可以匹配至少一个字符: "A\d+"

  • 修饰符? 可以匹配零个或1个字符:"A\d?"

  • 修饰符 {n} 可以匹配n个字符:"\d{6}"

  • 修饰符 {n,m} 可以匹配n-m个字符:"\d{3,5q}"

  • 修饰符 {n,} 可以匹配至少n个字符: "\d{3,}"

bash 复制代码
   /**
     * 匹配电话号码 区号-电话
     * @param s
     * @return
     */
    public static boolean isValidTel(String s) {
//        return s.matches("\\d{3,4}\\-\\d{6,8}");
        return s.matches("0\\d{2,3}\\-\\d{6,8}"); // 严谨一些, 我们想让区号以0开头,
    }

    public static void main(String[] args) {
        System.out.println(isValidTel("010-123456")); // true
        System.out.println(isValidTel("010-12345678")); // true
        System.out.println(isValidTel("0123-123456")); // true
        System.out.println(isValidTel("0123-12345678")); // true
        System.out.println(isValidTel("123-12345678")); // false
        System.out.println(isValidTel("123-0123456")); // false

        System.out.println(isValidTel("010#012345678")); // false
        System.out.println(isValidTel("010X012345678")); // false
        System.out.println(isValidTel("01-012345678")); // false
        System.out.println(isValidTel("01234-12345678")); // false
        System.out.println(isValidTel("01A-12345678")); // false
        System.out.println(isValidTel("0123-12345")); // false
        System.out.println(isValidTel("0123-12345X")); // false
        System.out.println(isValidTel("0123-123456789")); // false
        System.out.println(isValidTel("0123-12345678X")); // false

    }

正则表达式匹配规则总结:

2.1 复杂正则表达式

  • ^$ 匹配开头和结尾: "^A\d{3}$"

  • [...] 可以匹配范围内的字符: "[abc]1"

  • [...] 可以匹配范围内的字符: "[a-f]1"

  • [...] 可以匹配范围内的字符: "[a-f0-9]{6}"

  • [...] 可以匹配范围内的字符: "[a-f0-9_]{6}"

  • [^...] 可以匹配非范围内的字符: "[^0-9_]{6}"

  • AB|CD 可以匹配AB或CD:"java|pnp"

  • AB|CD 可以匹配AB或CD:"learn\s(java|php)"

  • AB|CD 可以匹配AB或CD:"learn\sjava|php"

bash 复制代码
/**
     * 匹配5-10位qq号码
     * @param s
     * @return
     */
    public static boolean isValidQQ(String s){
        return s.matches("^[1-9]\\d{4,9}$");
    }

/**
     * 匹配电话号码 区号-电话
     * @param s
     * @return
     */
    public static boolean isValidTel(String s) {
//        return s.matches("\\d{3,4}\\-\\d{6,8}");
//        return s.matches("0\\d{2,3}\\-\\d{6,8}"); // 严谨一些, 我们想让区号以0开头,
        return s.matches("0\\d{2,3}\\-[1-9]\\d{5,7}"); // 区号以0开头,并且电话号码1-9 数字开头
    }

正则表达式匹配规则:

3.1 分组匹配规则

  • (... ) 可以分组: "(\d{4})\-(\d{1,2})\-(\d{1,2})"

    正则表达式分组举例

  • 提取电话号码 ###-########

    不加小括号的作用是匹配, 加上小括号后,匹配完成后提取

  • 提取24小时时间 ##:##

String.matches vs Pattern.matcher:

反复使用一个正则表达式字符串进行快速匹配效率较低:

  • 可以把正则表达式字符串编译为Pattern对象

    使用Matcher.group(n) 可以快速提取子串:
java 复制代码
static Pattern p = Pattern.compile("^(0\\d{2,3})\\-([1-9]\\d{5,7})$");
    public static void parse(String s) {
        Matcher matcher = p.matcher(s);
        if (matcher.matches()) {
            System.out.println(matcher.group(0)); // 010-123456
            System.out.println(matcher.group(1)); // 010
            System.out.println(matcher.group(2)); // 123456
        }
    }

    public static void main(String[] args) {
        parse("010-123456");
    }

总结

正则表达式分组可以通过Matcher对象快速提取子串

  • group(0) 表示匹配的整个字符串
  • group(1) 表示第1子串
  • group(2) 表示第2个子串
  • ...

4. 非贪婪匹配

给定一个字符串表示的数字

  • 判断该数字末尾0的个数 ``

    正则表达式默认使用贪婪匹配:

  • 尽可能多地向后匹配

  • 使用? 实现非贪婪匹配

java 复制代码
  /**
     * 非贪婪匹配
     */

    public static void zeros(String s) throws IllegalAccessException {
//        Pattern p = Pattern.compile("^\\d+(0*)$"); //\d+ 默认贪婪匹配,尽可能的向后匹配,,所以后面0* 匹配的是空
        Pattern p = Pattern.compile("^\\d+?(0*)$"); //\d+? 开启贪婪匹配
        Matcher m = p.matcher(s);
        if (m.matches()) {
            String zeroStr = m.group(1);
            System.out.println(zeroStr.length());
        } else {
            System.out.println("not a number");
        }

    }

    public static void main(String[] args) throws IllegalAccessException {
        zeros("1231"); // 0
        zeros("12310"); // 1
        zeros("123100"); //2
        zeros("1231000");//3
    }

总结:

  • 正则表达式匹配默认使用贪婪匹配
  • 使用? 表示对某一规则进行非贪婪匹配
  • 注意区分?号的含义 \d??

5. 搜索和替换

使用正则表达式分割字符串

  • String[] String.split(String regex)

使用正则表达式搜索字符串

  • Matcher.find()

    匹配指定单词匹配所有单词 匹配单词中所有带o的单词

使用正则表达式替换字符串

  • String.replaceAll()
    将多个空格替换为1个空格

    对每个单词前后都加上<b>标签

总结

使用正则表达式可以:

  • 分割字符串 String.split()
  • 搜索字符串 Matcher.find()
  • 替换字符串 String.replaceAll()
相关推荐
lkbhua莱克瓦2417 分钟前
Java基础——常用API2
java·笔记·github·学习方法
丰锋ff35 分钟前
英一2016年真题学习笔记
笔记·学习
摇滚侠37 分钟前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记
新子y37 分钟前
【小白笔记】稀疏数组 (Sparse Array) 在计算机科学中的存储优化问题
笔记
Lynnxiaowen1 小时前
今天我们学习Linux架构keepalived实现LVS代理双击热备
linux·学习·架构·云计算
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式的使用,笔记96
spring boot·笔记
charlie1145141912 小时前
HTML 理论系统笔记2
前端·笔记·学习·html·基础·1024程序员节·原生
井队Tell2 小时前
打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第十天)
学习·3d·unity
Elias不吃糖2 小时前
Linux 环境适应 Day 1 全面笔记
linux·c++·笔记
爱奥尼欧2 小时前
【Linux笔记】网络部分——传输层协议TCP(1)
linux·运维·网络·笔记·tcp/ip·1024程序员节