正则表达式入门笔记

极客时间正则表达式入门课程笔记

正则常用的功能:校验数据有效性、查找符合要求的文本、对文本进行切合和替换。

元字符

元字符是正则的基本单元。它是正则表达式中具有特殊意义的专用字符。

元字符
分类备注
特殊单字符.任意字符(换行除外)
\d 任意数字 \D 任意非数字
\w 任意字母数字下划线 \W任意非字母数字下划线
\s 任意空白符 \S 任意非空白符
空白符\r 回车符
\n 换行符
\f 换页符
\t 制表符
\v 垂直制表符
\s 任意空白符
量词* 含义:0到多次
+ 含义:1到多次
? 含义:0到1次
{m} 含义:出现m次
{m,} 含义:出现至少m次
{m,n} 含义:m到n次
范围| 或,如ab|bc代表ab或bc
[...] 多选一,括号中任意单个元素
[a-z] 匹配a到z之间任意单个元素\n (按ASCII表,包含a,z)
[^...] 取反,不能是括号中的任意单个元素
### 三种模式

贪婪模式、非贪婪模式和独占模式。

贪婪模式:尽可能进行最大长度匹配。正则的量词默认是使用的贪婪模式。

非贪婪模式:匹配长度最小满足要求的。在量词后边加上?

独占模式:类似贪婪模式,会尽可能多的去匹配,不回溯。匹配过程中独占模式不会交还已经匹配上的字符,如果匹配失败就结束。在量词后边加+

举个例子解释一下什么是回溯,当时我也是看了好久才看明白。

regex = "xy{1,3}yz"

text = "xyyz"

匹配过程:在匹配y{1,3}时会尽可能长的去匹配,所以匹配到xy后还会使用y去匹配下一个是否时y,因为现在才匹配到了一个y。继续匹配xyy,现在两个 y。继续用第三个y匹配,发现下一个不是y。匹配两个y。继续匹配正则下一个规则,吐出当前字符z,接着用正则中的y去匹配吐出来的当前字符z,发现不匹配。向前回溯匹配一个y,然后继续匹配下一个规则匹配xy{1,3}yz中的y,然后匹配z。

非贪婪模式匹配

regex = "xy{1,3}?yz"

text = "xyyz"

匹配过程:在匹配y{1,3}?时会尽可能短的去匹配,所以当匹配到xy后使用正则中的y去匹配下一个字符,发现匹配。继续匹配z,发现匹配

独占模式匹配

regex = "xy{1,3}+yz"

text = "xyyz"

匹配过程:匹配到xyy,继续用y去匹配z匹配不上,然后继续正则中xy{1,3}+yz中的y的匹配。发现y和当前字符z不匹配,不回溯。导致匹配失败。

分组和引用

分组和编号

括号在正则中可以用于分组,被括号括起来的部分“子表达式”会被保存为一个自组。

第几个括号就是第几个分组。

例如将2021-06-21 21:24:05提取出日期和时间(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) 日期是第一个分组 时间是第二个分组。

不保存子组

在括号里使用?:不保存子组。不保存子组会提高正则性能,但是之后不能再利用括号中的值

括号嵌套

在复杂的括号嵌套中想要知道某个括号是第几个分组时怎么办?其实方法很简单,数左括号是第几个,就是第几个分组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zYSE80jC-1624546282681)(正则入门.assets/image-20210622185239877.png)]

日期分组编号是1,时间分组编号是5,年是2。

分组引用

知道了分组应用的编号,大部分情况,我们可以使用“反斜杠 + 编号”的方式进行引用。不同编程语言查找和替换的引用方式:

编程语言查找时引用方式替换时引用方式
Java\number 如\1$number 如$1
JavaScript$number 如$1$number 如$1
Go官方包不支持官方包不支持
Python\number 如\1\number 如\1
分组应引用在查找中使用

如果我们要查找文中重复出现的单词 可以使用\w+来表示一个单词,那么使用\w+ \1就是这个正则了。

在这里插入图片描述

四种匹配模式

不区分大小写模式、点号通配模式、多行模式和注释模式。

不区分大小写模式

正则不区分英文字母的大小写,放在正则的前边。

修饰符:(?i)

修饰符在括号内作用范围是这个括号内的正则,不是整个正则。

点号通配模式

又叫单行匹配模式,改变的是点号的匹配行为,让其可以匹配任何字符,包括换行。

修饰符:(?s)

多行匹配模式

修饰符:(?m)

通常情况下,^匹配字符串的开头,$匹配字符串的结尾。

场景:日志以时间开头,打印堆栈占用了多行,可以使用多行匹配模式,在日志中匹配到以时间开头的每一行日志。

注释模式

就是给正则加注释,更容易阅读和维护。

修饰符:(:# xxx)

断言

用于匹配位置,而不是内容本身。常见的断言:单词边界、行的开始或结束、环视。

单词边界

\b 匹配单词边界。

例如,精准匹配单词 \b\w+\b

行的开始/结束
  • ^ 匹配行的开始。多行模式时,可以匹配任意行开头
  • $ 匹配行的结束。多行模式是,可以匹配任意行结束
  • \A 仅匹配整个字符串的开始,不支持多行模式
  • \Z 进匹配整个字符串的结束,不支持多行模式
环视

匹配前后要满足某种规则。

正则名称含义示例
(?<=Y)肯定逆序环视左边是Y(?<=\d)X 匹配左边是数字的X
(?<!Y)否定逆序环视左边不是Y(?<!\d)th 匹配左边不是数字的th
(?=Y)肯定顺序环视右边是Ysix(?=\d) 匹配右边是数字的six
(?!Y)否定顺序环视右边不是Ysix(?!\d) 匹配右边不是数字的six

左尖括号代表看左边,没有尖括号看右边,叹号是非的意思。

左边不是数字,右边也不是数字的6位数:(?<!\d)[1-9]\d{5}(?!\d)

环视中虽然又括号,但是不会保存成子组。保存成子组的一般是匹配到的文本内容,后续用于替换等操作,而环视是表示对文本左右环境的要求,即环视只是匹配位置,不匹配文本内容。

常见问题及解决方案

数字

使用字符组、量词就能解决

  • 数字在正则中可以使用\d或者[0-9]来表示
  • 连续的多个数字使用\d+或[0-9]+
  • n位数据,可以使用\d{n}
  • 至少n为数据,可以使用\d{n,}
  • m-n数字,可以使用\d{m,n}
正数,负数和小数

如果希望正则能匹配到比如3,3.14,-3.3,+2.7等数字,需要注意的是,开头的正负符号可能有,也可能没有,所以可以使用[-+]?来表示,小数点和后面的内容也不一定会有,所以可以使用(?:.\d+)?来表示,因此匹配正数、负数和小数的正则可以写成[-+]?\d+(?:.\d+)?。

  • 非负整数,包含0和正整数,可以表示成[1-9]\d*|0
  • 非正整数,包括0和负整数,可以表示成-[1-9]\d*|0
浮点数

可以使用[-+]?\d+(?:\.\d+)?来表示

十六进制数

可以使用[0-9A-Fa-f]+

手机号码

在这里插入图片描述

身份证号码

第一代身份证:[1-9]\d{14}

第二代:[1-9]\d{14}(\d\d[0-9Xx])?

腾讯QQ号

目前QQ号不能以0开头,最长的有10位,最短的从10000(5位)开始。从规则上我们可以得知,首位是1-9,后面跟着是4到9位的数字,即可以使用[1-9][0-9]{4,9}来表示。

中文字符

中文属于多字节Unicode字符,中文的码值范围是4E00-9FFF之间。

不同的语言是表示方式有一些差异,比如在Python,Java,JavaScript中,Unicode可以写成\u码值来表示,即匹配中文的正则可以写成[\u4E00-\u9FFF],如果在PHP中使用,Unicode就需要写成\u(码值)的样式。

IPv4地址

IPv4地址通常表示成27.86.1.226的样式,4个数字用点隔开,每一位范围是0-255,比如从日志中提取出IP,如果不要求那么精确,一般使用\d{1,3}(\.\d{1,3}){3}就够了,需要注意点号需要转义。

精确:(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)(?:\.(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)){3}

网页标签

配对出现的标签,比如title,一般网页标签不区分大小写,我们可以使用(?i)<title>.*?</title>来进行匹配。在提取引号里面的内容时,可以使用[A"]+,方括号里面的内容时,可以使用[^>]+等方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值