正则表达式 理解和使用(持续更新 2020.05.29)

一.基本知识(部分)

本文大部分知识出自于 正则表达式-菜鸟教程 ,我将根据个人的一部分理解和使用经验转述为浅显易懂的知识,避免理解歧义。

1.核心内容

正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。是一种约定好的匹配规则,其本身就是一个字符串。正则表达式作为一个模板,与所搜索的字符串进行匹配。正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母、数字、标点符号等,而元字符则具有特殊的含义。

普通字符:
想要匹配 “https://www.csdn.net” 这样一个字符串,用正则表达式可以表示为:https://www.csdn.net,有人会觉得我糊弄人,这不是和原来的字符串一模一样嘛,我干嘛还用正则表达式,直接比较好了。嗯,没错,但这确实是正则表达式的使用方式之一,用简单的字符串去匹配,这是学习和理解正则表达式的基础。

元字符:
元字符是含有特殊含义的字符。元字符有很多,我如果全部按照教程或课本列取出来,大家不如直接到这里查看>> 元字符-菜鸟教程
在这里我记述几个比较重要的元字符:

元字符说明示例
\转义字符,和大多数语言的用法一样,用于和该字符后的一个或多个字符组成特殊含义的字符,或将元字符转义成普通字符\\ 表示匹配一个“\”;\n 表示匹配一个换行符
^匹配开始位置, 用于将该字符后的一个字符标记为开头^a 表示匹配以 a 开头的字符串
$匹配结束位置, 用于将该字符前的一个字符标记为结尾^b 表示匹配以 b 结尾的字符串
*匹配该字符前的一个字符或子表达式零次或多次c* 表示匹配零个 c 或 多个 c,可以匹配空字符串 “”
+匹配该字符前的一个字符或子表达式一次或多次d+ 表示匹配一个 d 或 多个 d
?匹配该字符前的一个字符或子表达式零次或一次e? 表示匹配零个 e 或 一个 e,可以匹配空字符串 “”
{n,m}匹配该字符前的一个字符或子表达式的次数,n与m需要满足:n >= 0且m >= 0且n <= m。表示至少匹配n次且至多匹配m次。相同的用法适用于{n}、{n,}f{2,5} 表示匹配2个 f 或 5个 f
.匹配除了换行符(\n、\r)之外的任何单个字符g.h 表示匹配以 g 开头 h 结尾的长度为 3 的字符串
|匹配该字符前或后的一个字符或子表达式i|g 表示匹配 i 或匹配 g,两者只匹配其一

单独说一下两个特殊的元字符:中括号[ ]、圆括号( )

元字符说明示例
[xyz]匹配 字符x 或 字符y 或 字符z,是单个匹配,类似 x|y|z[abc] 表示匹配 a 或 b 或 c
[^xyz]匹配不包含 字符x 或 字符y 或 字符z 的字符,是单个匹配,^只有在中括号内时才有“非”的含义[^abc] 表示匹配 a 或 b 或 c 之外的任意单个字符,如:可以匹配 e 或 f
---
(pattern)获取匹配,匹配pattern,pattern表示一个整体(hi) 表示匹配 hi,而不是匹配 h 或 i
(?:pattern)非获取匹配,匹配pattern(?:hello) 表示匹配 hello
(?=pattern)非获取匹配,正向肯定预查(look ahead positive assert),从任何匹配pattern开始处 开始匹配,即匹配字符串后面是patern的字符串,但并不匹配pattern如果一段字符串是 “hi,hi小明”,则 hi (?=小明) 表示匹配第二个 hi,而不匹配第一个hi
(?!pattern)非获取匹配,正向否定预查(negative assert),在任何不匹配pattern开始处 开始匹配,即匹配字符串后面不是patern的字符串,但并不匹配pattern如果一段字符串是 “hi,hi小明”,则 hi (?!小明) 表示匹配第一个 hi,不会匹配第二个 hi
(?<=pattern)非获取匹配,反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反如果一段字符串是 “小红,hi小红”,则 (?<=hi)小红 表示匹配第二个小红,不会匹配第一个小红
(?<!pattern)非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反如果一段字符串是 “小红,hi小红”,则 (?<!hi)小红 表示匹配第一个小红,不会匹配第二个小红

除此之外,还有一个特殊的字符 连字符“-”,它不是元字符,但是在中括号中可以用来表示一个字符范围,如:[a-z] 表示所有小写字母中的任意一个字母,[a-zA-Z] 表示所有大小写字母中的任意一个字母,同理,[0-9] 表示所有数字中的一个数字。

上述表中出现的 “子表达式” 是什么意思?先说一下什么是表达式,一个正则表达式就是一个表达式,子表达式就是表达式中的子串,都是相对概念,归根到底都是字符串[滑稽]。

2.案例

我们回到匹配 “https://www.csdn.net” 的路径问题上。通过上述学习,我们有很多方法可以匹配这地址,比如:^h.+t$[:\/\.a-z]+ 、……但是能匹配不代表在生产环境下可以使用,因为这两种方式的匹配都不够精确。
第一个表达式的意思是 匹配以 h 开头,以 t 结尾的长度大于2的任意字符串,那么它也可以匹配 haaaat;
第二个表达式的意思更夸张,匹配任何包含 : / . a-z 的长度大于0的字符串,那么它也可以匹配 //

最精确的匹配肯定是路径本身,但是我们既然学了正则表达式,就想着用一个表达式来尽可能多地重复匹配相似格式的字符串,做到重复利用。但是网址都是唯一的,用其本身匹配是最佳的方式,这个案例使用正则表达式匹配并不是明智之举,我们换一个案例来学习使用正则表达式。比如:匹配邮箱格式。

1)邮箱格式匹配

实际开发中,我们会收到用户使用邮箱注册账户或者获取验证码的请求,这个时候用正则表达式来验证用户输入的邮箱格式是否符合规范就再好不过了。

常见邮箱格式如下:

  • 123456789@qq.com
  • abcd@163.com
  • jack.work@gmail.com
  • li-ming@outbook.com

邮箱格式分析:

  1. 邮箱中有个@,且@前后不能紧挨 . - _ 等符号
  2. 邮箱不能以 . - _ 等符号开头或结尾
  3. 邮箱用户名部分可能存在 . - _ 数字 字母等字符
  4. 邮箱的域名不能以数字结尾
  5. 邮箱域名部分可能存在 . - _ 等符号

1、2、3、5 存在较难处理的部分,换个思路继续分析:

  1. 邮箱开头必须是 字母或数字
  2. 紧挨@前 必须是 字母或数字
  3. 紧挨@后 必须是 字母或数字
  4. 邮箱域名部分至少有一个 英文句号 .
  5. 邮箱结尾必须是小写字母
  6. 变化部分可能存在 . - _等特殊符号,且特殊符号不能连续出现

根据以上分析,我们建立了邮箱模型:
A[a]…A@A[a]…A
大A表示数字或字母,小a表示特殊字符

所以:
邮箱用户名部分的表达式是:^(?:[a-zA-Z0-9]+[-_\.]?)*[a-zA-Z0-9]
邮箱标识:@
邮箱域名部分的表达式是:(?:[a-zA-Z0-9]+[-_\.])+[a-zA-Z]+$
最后,我们得出匹配邮箱格式的正则表达式是:

String emailPattern = "^(?:[a-zA-Z0-9]+[-_\.]?)*[a-zA-Z0-9]@(?:[a-zA-Z0-9]+[-_\.])+[a-zA-Z]+$"

当然,在实际的开发环境中,对用户输入格式的要求更高,可能会采用多个表达式共同验证,如有纰漏,欢迎指正。


二.Java

1.字符串的matches(String regex)方法

Java字符串有个matches(String regex)方法,该方法返回布尔类型,要求是全匹配。比如"abcd123".matches("123") 返回的是false。

2.转义字符的运用

我们知道在Java中,反斜杠“\”表示转义字符,在正则表达式中,反斜杠也表示转义字符。所以,在Java中表示正则表达式中的一个“\”转义字符就是\\

有个绕脑的问题:在Java中怎么用正则表达式匹配一个反斜杠字符?
答案是:\\\\

既然是Java环境,首先就要考虑Java的语法。
Java中表示一个反斜杠字符是\\,而这一个反斜杠字符在正则表达式中却表示转义字符。
在正则表达式中表示一个反斜杠字符也是\\
因此,在Java中用正则表达式匹配一个 反斜杠字符 的写法就是\\\\

案例

1)Window路径匹配
String path = "C:\\Windows\\Google\\Chrome";  // 打印结果 C:\Windows\Google\Chrome
// 我现在要切换到 C:\Windows\Adobe\Photoshop,保持C:\Windows\不变,更改后面的路径怎么做?
String newPath = path.replaceAll("Google\\\\Chrome","Adobe\\\\Photoshop");  // 打印结果 C:\Windows\Adobe\Photoshop

小问号,你是不是有很多朋友??
"Google\\\\Chrome"这个,通过上面的讲解我们知道是 在Java中用正则表达式匹配一个反斜杠字符。
"Adobe\\\\Photoshop"这个,又是怎么回事?

这两个表达的意思其实是不一样的,先自行体会,等空闲了我再更新。

觉得不错,点个赞吧!
作者:@nokbita大雄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nokbita大雄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值