正则表达式

正则表达式

1.概念

  1. 为什么学习正则表达式?

    Java提供处理文本问题的技术,正则表达式(Regular Expression)是对字符串执行模式匹配的技术

2.了解正则表达式

package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/10:06
 * @Description: 体验正则表达式
 */
public class Regexp_1 {
    public static void main(String[] args) {
        //编写爬虫,从百度页面得到如下文本
        String content = "牟帆1997年农历6月29出生,当晚屋外电闪雷鸣,狂风骤起,刮了3000分钟。500次电闪雷鸣,显示这这个孩子的不凡!";

        //1. \d表示任意字符
        String regStr = "(\\d\\d)(\\d\\d)";
        //2.创建模式对象(正则表达式)
        Pattern compile = Pattern.compile(regStr);
        //3.创建匹配器
        Matcher matcher = compile.matcher(content);
        //4.开始匹配
        /**
         * matcher.find()  完成任务
         * 1. 根据指定的规则,定位满足规则的子字符串(比如1997)
         * 2.找到后,将 子字符串的开始的索引记录在 matcher 对象中 int[] groups 属性中
         *      groups[0]=2;把 该子字符串的结束的索引+1的值 记录到groups[1]=6中
         * 3. 同时记录oldLast值  字符串的结束的索引+1的值 即6;即下次执行find方法时,从oldLast的值4 开始匹配
         *
         *分组:比如 (\d\d)(\d\d),正则表达式中有()  表示分组
         * 例如:根据指定规则,定位满足规则的子字符串(比如(19)(97))
         *      (1)groups[0] = 2,把该子字符串的结束索引 +1 groups[1] = 6
         *       (2) 第一组()匹配到的子字符串:groups[2] = 2 ,groups[3] = 4
         *      (3)第二组()匹配到的子字符串:groups[4] = 4 , groups[5] = 6
         *        更多组。。。
         *
         *  public String group(int group) {
         *         if (first < 0)
         *             throw new IllegalStateException("No match found");
         *         if (group < 0 || group > groupCount())
         *             throw new IndexOutOfBoundsException("No group " + group);
         *         if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
         *             return null;
         *         return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
         *     }
         *
         *  1.根据 group[0]=2 和 group[1]=6 记录的位置。 从content中开始截取子字符串,并返回
         *
         *  如果再次执行find方法,从6开始匹配
         *
         *
         */
        while(matcher.find()){

            /*
            如果匹配规则有分组
                matcher.group(0)-----匹配到的子字符串
                matcher.group(1)-----匹配到的子字符串的第一组
                matcher.group(2)-----匹配到的子字符串的第二组
                。。。。。不能越界

             */
            System.out.println("匹配出所有4个任意数字:"+matcher.group(0));//1997 3000
            System.out.println("匹配到的第一组:"+matcher.group(1));//19
            System.out.println("匹配到的第二组:"+matcher.group(2));//87
        }
    }
}

3.正则表达式的语法

(1)元字符

元字符按功能分为: 
	(1)限定符
	(2)选择匹配符
	(3)分组组合和反向引用符
	(4)特殊字符
	(5)字符匹配符
	(6)定位符

元字符的转义符:\

什么情况下会用到转义符:* + ( ) $ / \ ? [ ] ^

I 字符匹配符

符号 符号 示例 解释 匹配输入
[ ] 可接收的字符列表 [efgh] e、f、g、h中的任意一字符 e、f、g、h
[^] 不可接收的字符列表 [^abc] 除a、b、c外任意一字符,包含数字和特殊字符 d、#、2、...
- 连字符 A-Z 任意单个大写字母 A、D、...
. 匹配除 \n 以外的任何字符 a..b 以 a 开头,b结尾,中间包括2个任意字符的长度为4的字符串 asdb、a#sb、...
\\d 匹配单个数字字符,相当于[0-9] \\d{3}(\\d) 包含3个或4个字符串 231、3445
\\D 匹配单个非数字字符,相当于[^0-9] \\D(\\d)* 以单个非数字字符开头,后接任意个数字字符串 a122zsxz、#12dssd
\\w 匹配单个数字、大小写字母字符。相当于[0-9a-zA-Z] \\d{3}\\w 以3个数字字符开头,长度为7的数字字母字符串 234abcd、12345Pe
\\W 匹配单个非数字、大小写字母字符,相当于[^0-9a-zA-Z] \\W+\\d 以至少一个非数字字母字符串开头,两个数字字符字符串结尾 #29、#@……45

Java 正则表达式默认是区分到小写

不区分大小写第一种方法:

​ (?i)abc 表示abc都不区分大小写

​ a(?i)bc 表示bc不区分大小写

​ a((?i)b)c 表示b不区分大小写

不区分大小写第二种方法:

//创建Pattern对象时,表示匹配对象时字母是不区分大小写的
Pattern compile = Pattern.compile(regexp,Pattern.CASE_INSENSITIVE);

案例

package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/9:50
 * @Description: 演示字符匹配的使用
 */
public class Test {
    public static void main(String[] args) {
        String content = "a11c8abc";
//        String regexp = "[a-z]";//匹配 a-z 任意一个字符
//        String regexp = "[A-Z]";//匹配 A-Z 任意一个字符
//        String regexp = "abc";//匹配 abc 字符串(默认区分大小写)
//        String regexp = "(?i)abc";//匹配 abc 字符串(不区分大小写)
//        String regexp = "[0-9]";//匹配 0-9 任意一个字符
//        String regexp = "[^a-z]";//匹配 不在 a-z 任意一个字符
//        String regexp = "[^0-9]";//匹配 不在 0-9 任意一个字符
//        String regexp = "[abc]";//匹配 在a、b、c中 任意一个字符
//        String regexp = "[^abc]";//匹配 不在a、b、c中 任意一个字符
//        String regexp = "\\w";//匹配 字母、数字、下划线 任意一个字符
//        String regexp = "\\W";//匹配 除字母、数字、下划线之外 任意一个字符
//        String regexp = "\\s";//匹配 空白字符(空格,制表符等) 任意一个字符
//        String regexp = "\\S";//匹配 除空白字符(空格,制表符等)以外 任意一个字符
        String regexp = ".";//匹配 \n之外的所有字符,如果匹配.本生要用转义字符 \\.
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(content);
        while(matcher.find()){
            System.out.println("匹配到:"+matcher.group(0));//a c
        }


    }
}

II 选择匹配符

符号 符号 示例 解释 匹配输入
| 匹配“|”之前或之后的表达式 ab|cd ab|cd ab、cd
package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/14:13
 * @Description: 选择匹配符
 */
public class Test1 {
    public static void main(String[] args) {
        String content = "timo 提莫 提 莫";
        String regexp = "ti|莫";
        //创建Pattern对象
        Pattern compile = Pattern.compile(regexp);

        //创建匹配器
        Matcher matcher = compile.matcher(content);
        while(matcher.find()){
            System.out.println("找到:"+matcher.group(0));
        }
    }
}

III 限定符

符号 含义 示例 说明 匹配输入
* 指定字符重复0次或n次(无要求) (abc)* 仅包含任意个abc的字符串,等效于\w* abc、sdsad
+ 指定字符重复1次或n次(至少一次) m+(abc)* 至少一个m开头,后接任意个abc字符串 m、mabc、msdsabc、msdsftabcabc
指定字符重复0次或1次(最多1次) m+abc? 至少一个m开头,后接最多一个abc字符串 m、mabc、msdsabc
只能输入n个字符 [abcd] 由a、b、c、d中字母组成任意长度为3的字符串 abc、dbc、adc
指定至少n个匹配 [abcd] 由abcd中字母组成的任意长度不小于3的字符串 aab、bdc、aabdc
指定至少 n 个但不多于 m 个匹配 [abcd] 由abcd中字母组成的任意长度不小于3,不大于5的字符串 abc、abcd、aaaa、bcdab
package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/14:36
 * @Description:演示限定符的使用
 */
public class Test2 {
    public static void main(String[] args) {
        String content ="11111111333243";
//        String regexp = "a{3}";// 表示匹配 aaa 的字符
//        String regexp = "1{4}";// 表示匹配 1111 的字符
//        String regexp = "\\d{2}";// 表示匹配 2位任意字符串
//        String regexp = "a{3,4}";// 表示匹配 aaa 或 aaaa (贪婪匹配,尽量匹配多的)
//        String regexp = "\\d{2,5}";// 表示匹配 2-5位数字字符串 (贪婪匹配,尽量匹配多的)
//        String regexp = "1+";// 表示匹配 一个1 或 多个 1
//        String regexp = "1*";// 表示匹配 0个1 或 多个 1
        String regexp = "a1?";// 表示匹配 a 或 a1
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(content);
        while(matcher.find()){
            System.out.println("找到:"+ matcher.group(0));
        }
    }
}

IIII 定位符

符号 含义 示例 说明 匹配输入
^ 指定起始字符 [1]+[a-z]* 以至少1个数字开头,后接任意个小写字母的字符串 123、6aa、555edf
$ 指定结束字符 [2]\\-[a-z]+$ 以1个数字开头后连接字符"-",并以至少1个小写字母结尾的字符串 1-a
\\b 匹配目标字符串的边界 han\\b 这里说的字符串的边界指的是子串间有空格,或者是目标字符串的结束位置
\\B 匹配目标字符串的非边界 han\\B 和\b的含义刚刚相反
package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/15:16
 * @Description:演示定位符的使用
 */
public class Test3 {
    public static void main(String[] args) {
        String content = "123abc cd bc";
        //以至少1个数字开头,后接任意个小写字母的字符串
//        String regexp = "^[0-9]+[a-z]*";
        //至少1个数字开头,必须以至少一个小写字母结束
//        String regexp = "^[0-9]+[a-z]+$";
//        String regexp = "c\\b"; //匹配边界(该字符串最后,或空格后子字符串的最后)c ------c c
        String regexp = "c\\B"; //匹配边界(该字符串开头,或空格后子字符串的开头)c ------c
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(content);
        while(matcher.find()){
            System.out.println("找到:"+matcher.group(0));
        }

    }
}

IIIII 分组

常用分组构造形式 说明
() 非命名捕获
(?) 命名捕获
package com.mf.study;

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

/**
 * @Author:mufan
 * @Date: 2022/06/11/15:38
 * @Description:分组
 */
public class Test4 {
    public static void main(String[] args) {
        String content = "moufan s3w423 df55f4fan";
        String regexp = "(?<g1>\\d)(\\d)";//匹配2位数
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(content);
        while(matcher.find()){
            System.out.println("找到:"+matcher.group(0));
            System.out.println("通过编号取第一组:"+matcher.group(1));
            System.out.println("通过组名获取第一组:"+matcher.group("g1"));
            System.out.println("第二组:"+matcher.group(2));
        }
    }
}


  1. 0-9 ↩︎

  2. 0-9 ↩︎

posted @ 2022-06-13 00:23  snail05  阅读(98)  评论(0)    收藏  举报