之前对于正则表达式的学习一知半解,这次就利用《正则表达式必知必会》这本书来从头到尾的梳理一下正则表达式的基本知识
我们在进行文本匹配的时候,最常用到的就是就是精确匹配,例如:检索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次以上的结果。例如: abc*匹配前面是ab,后面的c可以是没有,也可以是一个或者多个
str_view_all("abcasdqabqweqweabcccqwlejl", "abc*")
PS:重复匹配的规则只是适用于前面一个字符。如果想要多个字符一起,可以在多个字符之间添加()
有时候我们知道某一个字符存在但是不清楚是出现多少次。这个时候我们就可以使用+代表匹配一次或者多次。例如:ab[cd]+代表在匹配的时候,我们可以匹配到前面是ab,后面可以是c或者d。同时c或者d可以出现一次以上。
str_view_all("abcasdqabdqwerabccasdbabcddqowej", "ab[cd]+")
我们在匹配的时候,可能碰到某一个字符是否存在的情况。这个时候就可以使用?来代表0次或者一次。例如:abc?代表可以匹配到ab也可以匹配到abc
str_view_all("abaslkdjqabclaskjdabd", "abc?")
之前介绍的匹配符号,是用于我们不清楚要匹配多少次的时候使用的。有时候我们明白想要匹配某一个字符多少次。这个时候我们就可以使用{}来指定匹配次数了
我们可以在{}填入数字。代表重复多少次。例如:{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次就截止了。这个时候如何不想匹配那个的话,可以在后面使用环视。这个后面会有介绍
我们在使用+的时候代表至少重复一次。如果我们想要至少重复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即是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表示。这个非单词边界其实就是单词边界的反义了。例如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之前的两个字符