之前对于正则表达式的学习一知半解,这次就利用《正则表达式必知必会》这本书来从头到尾的梳理一下正则表达式的基本知识

正则表达式的用途

我们在进行文本匹配的时候,最常用到的就是就是精确匹配,例如:检索abcdfg当中是否含有abc。但是如果想要需要模糊搜索,例如:在一堆文件当中(ab011.txt, edf.txt, ab0ae.txt)找到查找倒数第三个是0的文件或者想要在一长串不同的变量当中提取特定的匹配的数据。例如:从abc03-2ndus-32当中只提取数字。等等。。。。这个时候就需要用到正则表达式了。

正则表达式:其实就是在进行检索的时候,通过特定的符号构建具有某一规律的表达式,进而检索出符合这种规律的结果。例如上面两个模糊匹配的需求 > 正则表达式存在于各种编程语言当中,这里我使用R语言来演示正则表达式的使用。

library(stringr)
# 查找倒数第三个是0的文件
str_view(c("ab011.txt", "edf.txt", "ab0ae.txt"), "0..\\.txt")
# 只提取数字
str_view_all("abc03-2ndus-32", "[0-9]+")

下面我们就基于《正则表达式必知必会》这本书了讲一下基本的正则表达式符号。

精确匹配普通文本

虽然正则表达式是有很多特定的匹配。但其实也包括基本的精确匹配。例如我们想要在一串字符当中检索检索abc的位置

str_view_all("abcqowjoqwjeabcalsjkdoqabcalskd", "abc")

模糊匹配

我们在进行字符匹配的时候,除了知道明确要匹配的结果。有时候可能需要匹配符合某一规律的字符。这个时候,我们可能匹配到的就是一组字符而不是一个字符了。

匹配任意字符:.

有时候我们知道其中的几个字符,但是不清楚中间某几个或者某几个字符的时候。我们就可以使用.来代表任意的一个字符。例如我们知道一串字符当中有ab和a但是中间的一个字符不记得了。那就可以用.来代替。

str_view_all("abcqowjoqwjeabcalsjkdoqabdalskd", "ab.a")

利用字符集合区间:

我们在进行匹配的时候,只某一个位置的大致的范围。这个时候就可以用到字符集合区间。我们使用[]代表集合区间。在[]内的字符代表满足其中一个即可。例如:a[ab]c代表匹配到abc或者aac都可以

# 使用.代表匹配左右字符
str_view_all("abcqowjoqwjeadcalsjkdoqaacalskd", "a.c")
# 使用[]匹配区间内字符
str_view_all("abcqowjoqwjeadcalsjkdoqaacalskd", "a[ab]c")

简化集合区间: -

对于常用的集合区间,例如有顺序的数字,按照字母表排列的字母。我们可以使用-来简化集合区间。例如[0-9]代表[0123456789][6-9]代表[6789]。对于字母而言:[A-Z]代表匹配从A到Z的所有大写字母。[a-z]代表匹配从a到z的所有小写字母。

str_view_all("asdsioqda1clasdjla5calsdja7c","a[1-5]c")

排除: [^]

之前选择特定的一组字符的时候,我们是顺向看某一个规律的。但是有时候顺向的规律没有反应的好使用,所以我们就可以通过排除反向的规律来得到想要的结果。在正则表达式当中,我们通过使用[^]代表排除某一组字符。例如:a[^1-5]c代表选择中间不是1-5的字符。

str_view_all("asdsioqda1clasdjla5calsdja7c","a[^1-5]c")

重复匹配

对于某一个特定规律的字符,有时候我们可能需匹配多次。

重复匹配多个字符

匹配0次或者多次: *

正则表达式当中,我们可以通过*来匹配0次以上的结果。例如: abc*匹配前面是ab,后面的c可以是没有,也可以是一个或者多个

str_view_all("abcasdqabqweqweabcccqwlejl", "abc*")

PS:重复匹配的规则只是适用于前面一个字符。如果想要多个字符一起,可以在多个字符之间添加()

匹配一次或者多次: +

有时候我们知道某一个字符存在但是不清楚是出现多少次。这个时候我们就可以使用+代表匹配一次或者多次。例如:ab[cd]+代表在匹配的时候,我们可以匹配到前面是ab,后面可以是c或者d。同时c或者d可以出现一次以上。

str_view_all("abcasdqabdqwerabccasdbabcddqowej", "ab[cd]+")

匹配0次或者一次: ?

我们在匹配的时候,可能碰到某一个字符是否存在的情况。这个时候就可以使用?来代表0次或者一次。例如:abc?代表可以匹配到ab也可以匹配到abc

str_view_all("abaslkdjqabclaskjdabd", "abc?")

匹配具体次数

之前介绍的匹配符号,是用于我们不清楚要匹配多少次的时候使用的。有时候我们明白想要匹配某一个字符多少次。这个时候我们就可以使用{}来指定匹配次数了

具体重复匹配: {num}

我们可以在{}填入数字。代表重复多少次。例如:{3}代表重复某一个字符3次。

str_view_all("abcqweabccasdqabccc", "abc+") #匹配c一次以上
str_view_all("abcqweabccasdqabccc", "abc{3}") # 匹配c三次

区间匹配: {,}

我们可以在{}填入两个数字来代表匹配这两个数字之间的次数。例如: {2,5}代编匹配某一个字符2-5之间的范围

str_view_all("abcqqqabcccccqweabcccccccqwej", "abc+") # 匹配c一次以上
str_view_all("abcqqqabcccccqweabcccccccqwej", "abc{2,5}") # 匹配c出现2-5次

PS:我们看到上面匹配的时候,最后哪个虽然c多于5次但是也匹配上了。只是说,只是匹配到5次就截止了。这个时候如何不想匹配那个的话,可以在后面使用环视。这个后面会有介绍

匹配至少重复多少次: {num, }

我们在使用+的时候代表至少重复一次。如果我们想要至少重复3次,那就不能使用了。这个时候我们就可以使用{3,}代表至少重复三次。

str_view_all("abcqqqabcccccqweabcccccccqwej", "abc{6,}")# 至少重复6次

防止过度匹配: ?

在所有的重复匹配符当中,都具有贪婪性,所谓的贪婪性是指其在匹配的时候,都是返回满足最大条件的结果,而不是最小的结果。这个时候如果我们想要其存在懒惰性。可以在重复匹配符后面添加一个?

贪婪性 懒惰性
* *?
+ +?
{} {}?
str_view_all("abcccccc", "abc{3,}")
str_view_all("abcccccc", "abc{3,}?")

边界匹配

我们在进行匹配的时候,经常需要定义这个匹配的边界。例如是字符串的开头还是结果这种的。这种时候就需要边界匹配

匹配字符串边界

匹配字符串开头: ^

我们可以通过^来匹配字符串的开头。 PS:需要注意的是,[^]代表非的意思

str_view(c("cat", "dqqcat"), "^cat")

匹配字符串结尾: $

我们可以通过$来匹配字符串的结尾。

str_view(c("ab011", "edf0dalq", "ab0ae"), "0..$")

匹配单词边界

单词边界: \b

除了开头和结尾,我们经常也需要匹配某一个单词的边界。这个时候我们就可以用到\b。其代表匹配单词的边界。可以是开头也可以是结尾。

b即是boundary的首字母

PS: 在R语言当中,\不可以直接使用需要转义,所以在R语言当中\\即代表\

str_view_all("The cat scat catt ", "cat") #匹配所有
str_view_all("The cat scat catt ", "\\bcat") #匹配开头
str_view_all("The cat-scat catt ", "cat\\b") #匹配结尾
str_view_all("The cat scat catt ", "\\bcat\\b") #匹配单词

PS:所谓的边界,并不是说空格就是边界了,这个边界指的是其实不是任何 的符号。这个边界代表的是是一个位置,它代表这一侧是一个是单词字符(**字母数字和下划线**)``另外一侧是非单词字符(除了**字母数字和下划线**之外的东西)中间的位置,或者一侧是非单词字符``另外一侧是单词字符中间的位置。例如:abc efg如果有加上边界的话则是abc\b \befg。代表这两个单词之间其实有两个边界的。

非单词边界: \B

除了单词边界,当然也就有非单词边界了。非单词边界我们用\B表示。这个非单词边界其实就是单词边界的反义了。例如abc - efg。我们的单词边界就是abc\b - \befg,那么她的非单词边界就是a\Bb\Bc \B-\B e\B\f\Bg。所以整体来说一段字符的非隐藏模式其实是^a\Bb\Bc\b \B-\B \be\Bf\Bg$

str_view_all("ab-cd ab - cd ", "\\B-\\B") #匹配非单词边界中间的-
str_view_all("ab-cd ab - cd ", "\\b-\\b") #匹配单词边界中间的-

子表达式: ()

我们在进行重复匹配的时候,一般来说所有的重复都是前面的一个字符。有时候我们想要让多个字符一起重复的话,这个时候就可以把他们捆绑到一起进行重复了。这种捆绑就是子表达式。我们通过()来实现表达式的捆绑

str_view_all("abcabcaaadwqabc","abc")
str_view_all("abcabcaaadwqabc","(abc){2}")

或: |

我们在正则表达式当中可以通过[]代表区其中一个,但是有时候我们需要多个字符之间的或的,这个时候就需要用到|来表示和。同时使用字表达来进行包括了

str_view_all("abcdcdasdabcdefqwe","ab(cd|ef){2}")

特殊字符

在正则表达式当中,我们还有一些特殊的字符代表一类特殊的符号。常用的特殊字符有:

特殊字符 说明
[\b] 退格符
\c 匹配一个控制字符
\d 匹配任意数字
\D \d的反义
\f 换页符
\n 换行符
\r 回车符
\s 匹配任意空白字符
\S \s的反义
\t 制表符
\v 垂直制表符
\w 匹配任意字母数字下划线
\W \w的反义
\x 匹配一个十六进制的数字
\0 匹配一个八进制的数字
str_view_all("dsd123sadoiqwjw132nasmd", "\\d+") #匹配所有数字
str_view_all("asd qowij ajksdj qioj", "\\W+") #匹配所有非字符

环视

我们在进行检索的时候,有时候想要匹配某一类条件之前或者之后的特定的字符。例如:我们想要在abcefgabefg当中匹配c后面的三个字符。这个时候就需要用到环视了。所有的环视表达式包括四种

种类 说明
(?=) 肯定式向后查看
(?!) 否定式向后查看
(?<=) 肯定式向前查看
(?<!) 否定式向前查看
str_view_all("abcefgabefg", "(?<=abc)\\w{3}") ##匹配abc之后的三个字符
str_view_all("abcefgabefg", "\\w{2}(?=ab)") ##匹配ab之前的两个字符