一文搞懂正则表达式基础语法以及如何应用

目录
  • 一、正则表达式
    • 1、基本介绍
    • 2、正则表达式语法
  • 二、正则语法
    • 1、字符匹配符、选择匹配符
    • 2、限定符
    • 3、定位符
    • 4、分组
  • 三、常用类
    • 1、基本介绍
    • 2、分组、捕获、反向引用
    • 3、String 类中使用正则表达式
  • 总结

一、正则表达式

1、基本介绍

概述

  1. 一个正则表达式,就是用某种模式去匹配字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用,不过,经过练习后就觉得这些复杂的表达式写起来还是相当简单的, 而且, 一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作缩短在几分钟(甚至几秒钟)内完成。
  2. 正则表达式不是只有java才有,实际上很多编程语言都支持正则表达式进行字符串操作!

快速入门

public class RegTheory {
    public static void main(String[] args) {
        //目标:匹配所有四个数字
        String content = "2002fsd ke ire i2222 ";

        //1. \\d 表示一个任意的数字
        String regStr = "(\\d\\d)(\\d\\d)";

        //2. 创建模式对象[即正则表达式对象]
        Pattern pattern = Pattern.compile(regStr);

        //3. 创建匹配器
        //说明:创建匹配器 matcher, 按照 正则表达式的规则 去匹配 content 字符串
        Matcher matcher = pattern.matcher(content);

        //4. 开始匹配
        while (matcher.find()) {
            System.out.println("找到: " + matcher.group(0));
            System.out.println("第 1 组()匹配到的值=" + matcher.group(1));
            System.out.println("第 2 组()匹配到的值=" + matcher.group(2));
        }
    }
}

底层源码

matcher.find() 完成的任务 (考虑分组),{什么是分组,比如 (\d\d)(\d\d) ,正则表达式中有() 表示分组,第 1 个()表示第 1 组,第 2 个()表示第 2 组...}
        1. 根据指定的规则 , 定位满足规则的子字符串 ( 比如 (20)(02))
        2. 找到后,将 子字符串的开始的索引记录到 matcher 对象的属性 int[ ] groups;
         ▷ groups[0] = 0 , 把该子字符串的结束的索引+1 的值记录到 groups[1] = 4
         ▷ 记录 1 组 () 匹配到的字符串 groups[2] = 0 groups[3] = 2
         ▷ 记录 2 组 () 匹配到的字符串 groups[4] = 2 groups[5] = 4
         ▷ 如果有更多的分组.....
        3. 同时记录 oldLast 的值为 子字符串的结束的 索引 +1 的值即 16, 即下次执行 find 时,就从 16  开始匹配。

 matcher.group(0) 分析

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();
}

根据 groups[0]=16 和 groups[1]=20  的记录的位置,从 content 开始截取子字符串返回

就是 [16,20) 包含 16  但是不包含索引为 20  的位置  如果再次指向 find 方法 . 仍然安上面分析来执行。

小结

1. 如果正则表达式有() 即分组
        2. 取出匹配的字符串规则如下
        3. group(0) 表示匹配到的子字符串
        4. group(1) 表示匹配到的子字符串的第一组字串
        5. group(2) 表示匹配到的子字符串的第 2 组字串
        6. ... 但是分组的数不能越界.

2、正则表达式语法

基本介绍

如果要想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:

①限定符,②选择匹配符,③分组组合和反向引用符,④特殊字符,⑤字符匹配符,⑥定位符

元字符(Metacharacter)-转义号

符号说明: 在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号。则检索不到结果,甚至会报错的。 案例:用$ 去匹配 “abc$(" 会怎样?

在Java的正则表达式中,两个\\ 代表其他语言中的一个\

需要用到转义符号的字符有以下 : " .  *  +  ()  $  /  \  ?  [  ]  ^  {  } "

二、正则语法

1、字符匹配符、选择匹配符

基本介绍

代码实现

String content = "a11c8abc _ABCy @";

String regStr = "[a-z]"; //匹配 a-z 之间任意一个字符

String regStr = "[A-Z]"; //匹配 A-Z 之间任意一个字符

String regStr = "abc"; //匹配 abc 字符串[默认区分大小写]

String regStr = "(?i)abc"; //匹配 abc 字符串[不区分大小写]

String regStr = "[0-9]"; //匹配 0-9 之间任意一个字符

String regStr = "[^a-z]"; //匹配 不在 a-z 之间任意一个字符

String regStr = "[^0-9]"; //匹配 不在 0-9 之间任意一个字符

String regStr = "[abcd]"; //匹配 在 abcd 中任意一个字符

String regStr = "\\D"; //匹配 不在 0-9 的任意一个字符

String regStr = "\\w"; //匹配 大小写英文字母, 数字,下划线

String regStr = "\\W"; //匹配 等价于 [^a-zA-Z0-9_]

// \\s 匹配任何空白字符(空格,制表符等)
String regStr = "\\s";

// \\S 匹配任何非空白字符 ,和\\s 刚好相反
String regStr = "\\S";

//. 匹配出 \n 之外的所有字符,如果要匹配.本身则需要使用 \\.
String regStr = ".";
//当创建 Pattern 对象时,指定 Pattern.CASE_INSENSITIVE, 表示匹配是不区分字母大小写.
Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);

选择匹配符

String content = "study hard";
String regStr = "t|a|r";

2、限定符

基本介绍

代码实现

String content = "a211111aaaaaahello";

String regStr = "a{3}"; // 表示匹配 aaa
String regStr = "1{4}"; // 表示匹配 1111
String regStr = "\\d{2}"; // 表示匹配 两位的任意数字字符

//细节:java 匹配默认贪婪匹配,即尽可能匹配多的
String regStr = "a{3,4}"; //表示匹配 aaa 或者 aaaa
String regStr = "1{4,5}"; //表示匹配 1111 或者 11111
String regStr = "\\d{2,5}"; //匹配 2 位数或者 3,4,5

//1+
String regStr = "1+"; //匹配一个 1 或者多个 1
String regStr = "\\d+"; //匹配一个数字或者多个数字

//1*
String regStr = "1*"; //匹配 0 个 1 或者多个 1

//遵守贪婪匹配
String regStr = "a1?"; //匹配 a 或者 a1

3、定位符

基本介绍

代码实现

String content = "123-abc sldkjfs s dfsjf";

String content = "123-abc";

//以至少 1 个数字开头,后接任意个小写字母的字符串
String regStr = "^[0-9]+[a-z]*";

//以至少 1 个数字开头, 必须以至少一个小写字母结束
String regStr = "^[0-9]+\\-[a-z]+$";

//表示匹配边界的 han[这里的边界是指:被匹配的字符串最后,也可以是空格的子字符串的后面]
String regStr = "han\\b";

//和\\b 的含义刚刚相反
String regStr = "han\\B";

4、分组

基本介绍

代码实现

String content = "hello world s7789 nn1189han";

//命名分组: 即可以给分组取名
String regStr = "(?<g1>\\d\\d)(?<g2>\\d\\d)";//匹配 4 个数字的字符串

Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);

while (matcher.find()) {
    System.out.println("找到=" + matcher.group(0));
    System.out.println("第 1 个分组内容=" + matcher.group(1));
    System.out.println("第 1 个分组内容[通过组名]=" + matcher.group("g1"));
    System.out.println("第 2 个分组内容=" + matcher.group(2));
    System.out.println("第 2 个分组内容[通过组名]=" + matcher.group("g2"));
}

三、常用类

1、基本介绍

概述

▷ java.util.regex 包主要包括以下三个类Pattern 类、Matcher 类和 PatternSyntaxException   ▷ Pattern 类
        pattern 对象是一个正则表达式对象。Pattern 类没有公共构造方法。要创建一个Pattern 对象 调用其公共静态方法,它返回一个Pattern 对象。该方法接受一个正则表达式作为它的第一个参数,比如: Pattern r=Pattern.compile(pattern);
  ▷ Matcher类
        Matcher对象是对输入字符串进行解释和匹配的引擎。 与Pattern 类一样, Matcher 也没有公共构造方法。 你需要调用 Pattern 对象的 matcher方法来获得一个 Matcher对象
  ▷ PatternSyntaxException
        PatternSyntaxException 是一个非强制异常类, 它表示一个正则表达式模式中的语法错误。

代码实例

public class PatternMethod {
    public static void main(String[] args) {
        String content = "hello abc hello, 努力学习";

        //String regStr = "hello";

        String regStr = "hello.*";

        boolean matches = Pattern.matches(regStr, content);

        System.out.println("整体匹配= " + matches);
    }
}

 Matcher 常用类

public class MatcherMethod {
    public static void main(String[] args) {
        String content = "hello edu jack edutom hello smith hello edu edu";

        String regStr = "hello";

        Pattern pattern = Pattern.compile(regStr);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println(matcher.start());
            System.out.println(matcher.end());
            System.out.println("找到: " + content.substring(matcher.start(), matcher.end()));
        }

        //整体匹配方法,常用于,去校验某个字符串是否满足某个规则
        System.out.println("整体匹配=" + matcher.matches());

        //完成如果 content 有 edu 替换成 努力学习
        regStr = "edu";
        pattern = Pattern.compile(regStr);
        matcher = pattern.matcher(content);

        //注意:返回的字符串才是替换后的字符串 原来的 content 不变化
        String newContent = matcher.replaceAll("努力学习");

        System.out.println("newContent=" + newContent);
        System.out.println("content=" + content);
    }
}

2、分组、捕获、反向引用

基本介绍

1、分组

我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看作是一个子表达式(一个分组)。

2、捕获

把正则表达式中子表达式(分组匹配)的内容,保存到内存中以数字编号或显式命名的组里, 方便后面引用, 从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以以此类推,组0代表的是整个正则式。

3、反向引用

圆括号的内容被捕获后,可以在这个括号后被使用, 从而写出一个比较实用的匹配式,这个我们称为反向引用,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部,内部反向引用\\分组号,外部反向引用$分组号。

经典案例

public class RegExp13 {
    public static void main(String[] args) {
        String content = "我....我要....学学学学....编程 java!";

        //1. 去掉所有的.
        Pattern pattern = Pattern.compile("\\.");
        Matcher matcher = pattern.matcher(content);
        content = matcher.replaceAll("");

        //2. 去掉重复的字 我我要学学学学编程 java!
        //(1) 使用 (.)\\1+
        //(2) 使用 反向引用$1 来替换匹配到的内容
        // 注意:因为正则表达式变化,所以需要重置 matcher

        pattern = Pattern.compile("(.)\\1+");//分组的捕获内容记录到$1

        matcher = pattern.matcher(content);

        //使用 反向引用$1 来替换匹配到的内容
        content = matcher.replaceAll("$1");

        System.out.println("content=" + content);
    }
}

3、String 类中使用正则表达式

替换功能

String 类:  public String replaceAll(String regex,String replacement)

判断功能

String 类:  public boolean matches(String regex){} // 使用 Pattern Matcher

分割功能

String 类:  public String[] split(String regex)

代码实例

String content = "2000 年 5 月,JDK1.3、JDK1.4 和 J2SE1.3 相继发布。";

//使用正则表达式方式,将 JDK1.3 和 JDK1.4 替换成 JDK
content = content.replaceAll("JDK1\\.3|JDK1\\.4", "JDK");

System.out.println(content);
//要求 验证一个 手机号, 要求必须是以 138 139 开头的
content = "13888889999";

if (content.matches("1(38|39)\\d{8}")) {
    System.out.println("验证成功");
} else {
    System.out.println("验证失败");
}
//要求按照 # 或者 - 或者 ~ 或者 数字 来分割
content = "hello#abc-jack12smith~北京";

String[] split = content.split("#|-|~|\\d+");

for (String s : split) {
    System.out.println(s);
}

总结

到此这篇关于正则表达式基础语法以及如何应用的文章就介绍到这了,更多相关正则表达式基础语法及应用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 正则表达式语法规则及在Javascript和C#中的使用方法

    一.正则表达式概念: 在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串.在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容.许多程序设计语言都支持利用正则表达式进行字符串操作. 二.正则表达式的使用: 正则表达式在ASP.NET中主要是用来对输入的内容进行验证,验证一般分为两种一种是客户端JS验证,另一种是服务器端验证 1.JS对输入内容验证 复制代码 代码如下: function check() {           

  • 关于正则表达式基本语法的应用详解(必看篇)

    1.正则表达式基本语法 两个特殊的符号'^'和'$'.他们的作用是分别指出一个字符串的开始和结束.例子如下: "^The":表示所有以"The"开始的字符串("There","The cat"等): "of despair$":表示所以以"of despair"结尾的字符串: "^abc$":表示开始和结尾都是"abc"的字符串--呵呵,只有&qu

  • 常用正则表达式语法例句

    这里有一些可能会遇到的正则表达式示例:  /^\[ \t]*$/ "^\[ \t]*$" 匹配一个空白行.  /\d{2}-\d{5}/ "\d{2}-\d{5}" 验证一个ID号码是否由一个2位字,一个连字符以及一个5位数字组成.  /<(.*)>.*<\/\1>/ "<(.*)>.*<\/\1>" 匹配一个 HTML 标记.  下表是元字符及其在正则表达式上下文中的行为的一个完整列表:  字符 

  • 正则表达式(语法篇推荐)

    正则表达式的构造摘要 构造 匹配 字符 x 字符 x \\ 反斜线字符 \0n 带有八进制值 0 的字符 n (0 <= n <= 7) \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7) \0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3.0 <= n <= 7) \xhh 带有十六进制值 0x 的字符 hh \uhhhh 带有十六进制值 0x 的字符 hhhh \t 制表符 ('\u0009') \n 新行(换行)符

  • 正则表达式语法

    正则表达式语法一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式.该模式描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配. 这里有一些可能会遇到的正则表达式示例: JScript VBScript 匹配 /^\[ \t]*$/ "^\[ \t]*$" 匹配一个空白行. /\d{2}-\d{5}/ "\d{2}-\d{5}" 验证一个 ID 号码是否由一个 2 位数字

  • 正则表达式基本语法详解

    正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符").模式描述在搜索文本时要匹配的一个或多个字符串. 1.正则表达式基本语法 两个特殊的符号'^'和'$'.他们的作用是分别指出一个字符串的开始和结束.例子如下: "^The":表示所有以"The"开始的字符串("There","The cat"等): "of despair$":表示所以以&q

  • 正则表达式的语法

    正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取出符合某个条件的子串等. 列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的. 构造正则表达式的方法和创建数学表达式的方法一样.也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式.正则表达式的组件可以是单个的字符.字符集合.字符范围.字符间的选择或者所有这些组件

  • 一文搞懂正则表达式基础语法以及如何应用

    目录 一.正则表达式 1.基本介绍 2.正则表达式语法 二.正则语法 1.字符匹配符.选择匹配符 2.限定符 3.定位符 4.分组 三.常用类 1.基本介绍 2.分组.捕获.反向引用 3.String 类中使用正则表达式 总结 一.正则表达式 1.基本介绍 概述 一个正则表达式,就是用某种模式去匹配字符串的一个公式.很多人因为它们看上去比较古怪而且复杂所以不敢去使用,不过,经过练习后就觉得这些复杂的表达式写起来还是相当简单的, 而且, 一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作缩短

  • 一文搞懂Java正则表达式的使用

    目录 1.什么是正则表达式 2.快速入门案例 3.正则表达式语法 转义符号 字符匹配符 字符匹配符演示 选择匹配符 正则限定符 正则定位符 1.什么是正则表达式 在了解正则表达式之前,我们先看几个非常常见的问题: 如何判断字符串是否是有效的电话号码?例如:010-1234567,123ABC456,13510001000等: 如何判断字符串是否是有效的电子邮件地址?例如:test@example.com,test#example等: 如何判断字符串是否是有效的时间?例如:12:34,09:60,

  • 一文搞懂Golang文件操作增删改查功能(基础篇)

    前言 目前,Golang 可以认为是服务器开发语言发展的趋势之一,特别是在流媒体服务器开发中,已经占有一席之地.很多音视频技术服务提供商也大多使用 Golang 语言去做自己的后台服务开发,业内貌似已经达成了某种共识.今天我们不聊特别深奥的机制和内容,就来聊一聊 Golang 对于文件的基本操作. 正文 开始之前,讲一个非常有意思的小桥段.最开始接触 Golang 这种语言的时候,我总感觉它和 Google 单词比较像,所以一度怀疑二者有什么联系.后来一查才发现,二者确实有联系,晕- -因为 G

  • 一文搞懂Vue3.2中setup语法糖使用

    目录 前言 一.如何使用setup语法糖 二.data数据的使用 三.method方法的使用 四.watchEffect的使用 五.watch的使用 六.computed计算属性的使用 七.props父子传值的使用 八.emit子父传值的使用 九.获取子组件ref变量和defineExpose暴露 十.路由useRoute和useRouter的使用 十一.store仓库的使用 十二.await 的支持 十三.provide 和 inject 祖孙传值 前言 提示:Vue3.2 版本开始才能使用语

  • 一文搞懂SQL注入攻击

    目录 1. 前言 2. SQL注入简介 (1)SQL语言 (2)SQL注入 3. SQL注入步骤 (1)发现漏洞 (2)信息收集 (3)攻击Web系统(猜解用户名和密码) (4)获取管理员权限 4. 防范SQL注入 (1)使用参数化查询或存储过程 (2)用户输入检测 (3)SQL语法分析 (4)其他 1. 前言 随着互联网的发展和普及,网络安全问题越来越突出,网络在为用户提供越来越多服务的同时,也要面对各类越来越复杂的恶意攻击.SQL注入(SQL Injection)攻击是其中最普遍的安全隐患之

  • 一文搞懂TypeScript的安装、使用、自动编译的教程

    1. 初识 TypeScript 上篇文章给大家介绍过TypeScript的安装.使用.自动编译的实现  需要的朋友点击查看. TypeScript 的介绍 TypeScript 是一种由微软开发的开源.跨平台的编程语言.它是 JavaScript 的超集,最终会被编译为 JavaScript 代码. 2012 年 10 月,微软发布了首个公开版本的 TypeScript,2013 年 6 月 19 日,在经历了一个预览版之后微软正式发布了正式版 TypeScript TypeScript 的作

  • 一文搞懂Python的hasattr()、getattr()、setattr() 函数用法

    目录 hasattr() getattr() setattr() hasattr() hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法.该函数的语法格式如下: hasattr(obj, name) 其中 obj 指的是某个类的实例对象,name 表示指定的属性名或方法名,返回BOOL值,有name特性返回True, 否则返回False. 例子: class demo: def __init__ (self): self.name = "lily" def sa

  • 一文搞懂JavaScript中bind,apply,call的实现

    目录 bind.call和apply的用法 bind call&apply 实现bind 实现call和apply 总结 bind.call和apply都是Function原型链上面的方法,因此不管是使用function声明的函数,还是箭头函数都可以直接调用.这三个函数在使用时都可以改变this指向,本文就带你看看如何实现bind.call和apply. bind.call和apply的用法 bind bind()方法可以被函数对象调用,并返回一个新创建的函数. 语法: function.bin

  • 一文搞懂C++ 动态内存

    了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的.C++ 程序中的内存分为两个部分: 栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存. 很多时候,您无法提前预知需要多少内存来存储某个定义变量中的特定信息,所需内存的大小需要在运行时才能确定. 在 C++ 中,您可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址.这种运算符即new 运算符. 如果您不再需要动态分配的内存空间,

  • 一文搞懂MySQL预编译

    1.预编译的好处 大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能.什么是预编译功能呢?它有什么好处呢? 当客户发送一条SQL语句给服务器后,服务器总是需要校验SQL语句的语法格式是否正确,然后把SQL语句编译成可执行的函数,最后才是执行SQL语句.其中校验语法,和编译所花的时间可能比执行SQL语句花的时间还要多. 如果我们需要执行多次insert语句,但只是每次插入的值不同,MySQL服务器也是需要每次都去校验SQL语句的语法格式,以及编译,这就浪费了太多的时

随机推荐