正则表达式快速入门

2022-09-01 13:00:41 浏览数 (1)

前言

说起正则表达式( Regular Expression ),很多人都会头疼,记命令都要记得吐血,不过正则表达式的效率真的是高的一比,完全可以从文本中筛选出你想要的任何内容,所以还是得学啊,并且如果没有正则表达式的话, Linux 也不会那么高效。这玩意以前已经学习过一遍了,没有怎么练习加上过去了好久又给全忘了,因此又得重新再学一遍 == ,其实也没有太多东西,但是要经常练习才能熟练。

常用元字符

元字符不是普通的字符,是代表了某种意义的字符,这里就把基本的元字符给记下来 (如果要匹配的东西是元字符的话要用 转义)

元字符

意义

b

匹配单词的开始或结束( 中间不少于 1 个 w )

w

匹配字母、数字、下划线、汉字

s

匹配任意的空白符( Tab、空格、换行符 )

d

匹配一个数字

.

匹配除换行符之外的任意字符

^

匹配字符串的开头

$

匹配字符串的结尾

[]

匹配 [] 里的内容

()

给括号内表达式分组

B

匹配不是单词开头或结束的位置

W

匹配任意不是字⺟,数字,下划线,汉字的字符,相当于 [^w]

S

匹配任意不是空⽩符的字符

D

匹配任意⾮数字的字符,相当于 [^d]


#这里说的单词并不是英语单词,是不少于一个 w 的东西,更精确的说法,b 匹配这样的位置:它的前⼀个字符和后⼀个字符不全是(⼀个是,⼀个不是或不存在) w

举个例子

bw{6}b 匹配 刚好6个字符的单词

^d{5,10}$ 匹配你在表单里填写的 5 到 10 位的 QQ 号

重复匹配

上面给的例子中就已经给出了重复的概念了,有了重复的概念,正则表达式才更加简洁高效,下面是一些有关重复的限定符

限定符

意义

*

重复 0 次或更多次

重复 1 次或更多次

?

重复 0 次或 1 次

{n}

重复 n 次

{n,}

重复 n 次或更多次

{n, m}

重复 n 到 m 次

字符匹配

前面已经匹配过数字、空白、字母了,如果想自己定义一个集合取匹配呢,这时要用到我们另外一个元字符 [] 了,它匹配的是一个字符

元字符

意义

[0-9]

匹配数字,相当于 d

[.?!]

匹配 . 或 ? 或 !

[a-z0-9A-Z]

匹配字母、数字、下划线,相当于 w (如果没有中文的情况下)

[^0-9]

匹配除数字外的任意字符,相当于 [^d]


注意 [] 里不用加入空格,否则会把空格给匹配,出现元字符也不用转义,因为它们此时代表的就是普通的字符

举个例子

(?0d{2}[) -]?d{8} 就可以匹配 (010)88886666022-22334455 以及 02912345678 这些格式的号码。

逻辑分支条件

有时候我们的正则表达式可能会匹配到我们不想要的数据,比如上面那个例子就会匹配到 ` 010)12345678 ` 以及 (022-87654321 这样格式的数据,要解决这个问题我们可以用分支条件( 也就是逻辑或 | )写多一点表达式,只要满足其中的一项就成功匹配到。

举个例子

0d{2}-d{8}|0d{3}-d{7} 这个表达式能匹配两种以连字号分隔的电话号码:

  1. 三位区号,如 010-12345678
  2. 四位区号,如 0376-2233445

#分支条件也有短路效应,只要匹配了左边的表达式就不会再去匹配右边的,所以写的时候要注意顺序。

分组

之前已经介绍了单个字符的重复,如果想让多个字符重复的话,我们可以用 () 将想要重复的字符括起来让它变成一个分组或者子表达式,然后在括号后面就可以像之前那样用重复限定符了。

举个例子

` ((2[0- 4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]? dd?) 用来匹配 ip 地址,其实就是重复了 3 次 2[0-4]d|25[0-5]|[01]?dd?` 表达式,不难分析。

后向引用

前面用的 () 实现了多个字符的重复,直接紧跟在后面加上限定符就行了,如果我们不想重复匹配多次,而是要在后面引用这次匹配到的内容该怎么办呢,我们可以用后向引用

每次用 () 进行一次分组时,() 里的内容都会拥有一个分组,从 1 开始一直递增,第 0 个分组是整个正则表达式本身,所以 1 就表示重复一次第一个分组捕获到的内容。

举个例子

b(w )bs 1b 可以用来匹配重复的单词,如 so sob(w )b 表示匹配一个单词,(w ) 就是分组 1 , s 表示一个或多个空白符,紧接着就是 1,也就是上次匹配到的单词,然后就以这个单词结束。

零宽断言

零宽断言分为后行断言和先行断言,它们是特殊类型的非捕获组 (也就是说匹配的不是自己,是别人),因为只匹配模式,不占字符,所以叫做零宽。当我们在一种特定模式之前或者之后有这种模式时,会优先使用断言(尤其是匹配 HTML 元素时)。

举个例子

我们想获取输入字符串 4.44 and 10.88 中 字符之后的所有数字。我们可以使用这个正则表达式 (?<=

断言模式

意义

(?=exp)

正向先行断言(positive lookhead),断⾔⾃⾝出现的位置的后⾯能匹配表达式exp

(?<=exp)

正向后行断言(positive lookbehind),断⾔⾃⾝出现的位置的前⾯能匹配表达式exp

(?!exp)

负向先行断言(negative lookhead), 断⾔此位置的后⾯不能匹配表达式exp

(?<!exp)

负向后行断言(negative lookbehind),断⾔此位置的前⾯不能匹配表达式exp

举个例子

代码语言:javascript复制
// positive lookhead
`sinM.`.match(/sin(?=M.)/g); // ["sin"]
`M.sin`.match(/sin(?=M.)/g); // null
// positive lookbehind
'sinM.'.match(/(?<=M.)sin/g); // null
'M.sin'.match(/(?<=M.)sin/g); // ["sin"]
// negative lookhead
`M.sin`.match(/sin(?!M.)/g); // ["sin"]
`sinM.`.match(/sin(?!M.)/g); // null
// negative lookbehind
'sinM.'.match(/(?<!M.)sin/g); // ["sin"]
'M.sin'.match(/(?<!M.)sin/g); // null

再举个例子

` (?<=<(w )>).*(?=</1>) 匹配 不包含属性的简单HTML标签内⾥的内容,好好思考一下,上面这个表达式可以将 <p>RE</p>` 中的 RE 给匹配出来。

贪婪与懒惰匹配

正则表达式跟人一样,都是贪婪的,所以当有可重复的限定符时,正则表达式会匹配最长的那个结果,有时我们不想让他变得那么贪婪,就可以用懒惰匹配,也就是在限定符后面加个 ?

限定符

意义

*?

重复任意次,但尽可能少重复

?

重复1次或更多次,但尽可能少重复

??

重复0次或1次,但尽可能少重复

{n,m}?

重复n到m次,但尽可能少重复

{n,}?

重复n次以上,但尽可能少重复

处理标记

标记

描述

i

不区分大小写: 将匹配设置为不区分大小写。

g

全局搜索: 搜索整个输入字符串中的所有匹配。

m

多行匹配: 会匹配输入字符串每一行。

代码语言:javascript复制
"/.at(.)?$/" => The fat
                cat sat
                on the mat.
// 这样只会匹配 mat           

"/.at(.)?$/gm" => The fat
                cat sat
                on the mat.
// 这样会匹配 fat sat mat 

参考文章 1 参考文章 2 参考文章

0 人点赞